gpt4 book ai didi

python - 从 Python 中的嵌套子类访问父变量

转载 作者:行者123 更新时间:2023-11-28 16:41:25 35 4
gpt4 key购买 nike

我想知道从嵌套子类访问父变量的最佳方式是什么,目前我正在使用装饰器。

这是唯一/最好的方法吗???

我不想直接访问父变量(例如 ComponentModel.origin(见下文)),因为这需要在“配置”文件中添加更多代码,所以我想知道我是否可以分配父变量相关子类继承的类中的变量?

我当前解决方案的简单示例:

# defined in a big library somewhere:
class LibrarySerialiser(object):
pass

# defined in my module:
class ModelBase:
pass

class SerialiserBase(LibrarySerialiser):
def __init__(self, *args, **kwargs):
# could i some how get hold of origin here without the decorator?
print self.origin
super(SerialiserBase, self).__init__(*args, **kwargs)

def setsubclasses(cls):
cls.Serialiser.origin = cls.origin
return cls

# written by "the user" for the particular application as the
# configuration of the module above:

@setsubclasses
class ComponentModel(ModelBase):
origin = 'supermarket'

class Serialiser(SerialiserBase):
pass


ser = ComponentModel.Serialiser()

这显然是一个简单的示例,它错过了所有真正的逻辑,因此许多类看似无效,但确实是必要的。

最佳答案

仅供引用,在嵌套类时使用的公认术语是内部/外部,而不是父/子或超/子类。父/子或超/子关系是指继承。这会使您的装饰器名称 setsubclasses 令人困惑,因为不涉及任何子类!

您在这里做的不寻常的事情是将类用作命名空间而不实例化它。通常你会实例化你的 ComponentModel 并且在那个时候,给你的 Serialiser 内部类一个来自其外部类的属性的副本是微不足道的.例如:

class ModelBase(object):
def __init__(self):
self.Serialiser.origin = self.origin

# ... then

cm = ComponentModel()
ser = cm.Serialiser()

更好的是,让外部类实例化内部类并将其传递给外部类的引用;然后它可以在需要时获取它自己想要的任何属性:

class ModelBase(object):
def __init__(self, *args, **kwargs):
serialiser = self.Serialiser(self, *args, **kwargs)

class SerialiserBase(LibrarySerialiser):
def __init__(self, outer, *args, **kwargs):
self.outer = outer
print self.outer.origin
super(SerialiserBase, self).__init__(*args, **kwargs)

# ...

cm = ComponentModel()
ser = cm.serialiser

但是,如果你坚持在不实例化外部类的情况下能够获取这个属性,你可以使用元类来设置属性:

class PropagateOuter(type):
def __init__(cls, name, bases, dct):
type.__init__(cls, name, bases, dct)
if "Serialiser" in dct:
cls.Serialiser.outer = cls

class ModelBase(object):
__metaclass__ = PropagateOuter

# Python 3 version of the above
# class ModelBase(metaclass=PropagateOuter):
# pass

class SerialiserBase(LibrarySerialiser):
def __init__(self, *args, **kwargs):
print self.outer.origin
super(SerialiserBase, self).__init__(*args, **kwargs)

class ComponentModel(ModelBase):
origin = 'supermarket'

class Serialiser(SerialiserBase):
pass

ser = ComponentModel.Serialiser()

这并没有做你的装饰器没有做的任何事情,但用户通过继承自动获得它,而不是必须手动指定它。 Python 之禅说“显式优于隐式”,所以番茄,番茄。

您甚至可以编写元类,以便它内省(introspection)外部类并将对该类的引用放入每个内部类,而不管它们的名称。

顺便说一句,您这样做的一个缺陷是您所有的模型类必须SerialiserBase 的子类。如果您的类的用户只想要默认序列化器,他们不能只在类定义中编写 Serialiser = SerialiserBase,他们必须编写 class Serialiser(SerialiserBase ): 通过。这是因为只有一个 SerialiserBase 并且它显然不能包含对多个 外部类的引用。当然,您可以编写您的元类来处理这个问题(例如,如果它已经具有 outer 属性,则通过自动创建指定序列化程序的子类)。

关于python - 从 Python 中的嵌套子类访问父变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18801191/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com