【问题标题】:python class propertiespython类属性
【发布时间】:2012-07-25 10:13:12
【问题描述】:

我正在尝试找到扩展类变量的最佳方法。希望到目前为止我提出的方法的一个示例可以说明这一点。

class A(object):
    foo = ['thing', 'another thing']

class B(A):
    foo = A.foo + ['stuff', 'more stuff']

所以我试图让子类继承并扩展父类的类变量。上面的方法有效,但似乎有点笨拙。我愿意接受任何建议,包括使用完全不同的方法完成类似的事情。

显然,如果需要,我可以继续使用此方法,但如果有更好的方法,我想找到它。

【问题讨论】:

  • foo 需要成为 class property 而不仅仅是实例属性是什么? (就此而言,鉴于列表是可变的,您可以在__init__ 时间更改类属性。)
  • 恕我直言,你所拥有的对我来说看起来不错(我想不出更干净的方法来做到这一点)。顺便说一句,我会称这些“类属性”,而不是“类属性”,因为属性是不同的(通常由 property 内置函数/装饰器创建)。
  • @kojiro 他不是指那些属性,他只是指属性。
  • 我避免在 init 中将其初始化为实例变量的主要原因是代码的简洁性。如果我不需要 init 用于任何其他目的,我宁愿避免编写一个,以及(IMO)丑陋的 super()__init__() 调用只是为了初始化一个变量。
  • IMO,上面显示的方式是完全干净的。静态变量绑定到一个类。继承时,新的静态变量将绑定到最子类。重新定义它可以清楚地表明您在 B 中也有一个静态 foo。除此之外,这对我来说似乎是一个设计问题,因为这种“模式”不仅非常罕见,而且也不是真正的继承模式。

标签: python class variables


【解决方案1】:

可以使用元类:

class AutoExtendingFoo(type):

    def __new__(cls, name, bases, attrs):
        foo = []
        for base in bases:
           try:
               foo.extend(getattr(base, 'foo'))
           except AttributeError:
               pass
        try:
            foo.extend(attrs.pop('foo_additions'))
        except KeyError:
            pass
        attrs['foo'] = foo
        return type.__new__(cls, name, bases, attrs)

class A(object):
    __metaclass__ = AutoExtendingFoo
    foo_additions = ['thing1', 'thing2']
    # will have A.foo = ['thing1', 'thing2']

class B(A):
    foo_additions = ['thing3', 'thing4']
    # will have B.foo = ['thing1', 'thing2', 'thing3', 'thing4']

class C(A):
    pass
    # will have C.foo = ['thing1', 'thing2']

class D(B):
    pass
    # will have D.foo = ['thing1', 'thing2', 'thing3', 'thing4']

【讨论】:

  • 不错,但违反了最小意外原则。也许分配给__add_to_foo__,而是假装我们从object继承了一个空的foo
【解决方案2】:

我肯定会选择实例属性。 (如果我猜对了,对于你的情况,它们不一定是静态的?!)

>>> class A:
...     @property
...     def foo(self):
...         return ['thin', 'another thing']
...
>>> class B(A):
...     @property
...     def foo(self):
...         return super().foo + ['stuff', 'thing 3']
...
>>> B().foo
['thin', 'another thing', 'stuff', 'thing 3']

【讨论】:

  • 如果您经常访问这些数据,这并不是特别有效。您必须在 A 上进行属性查找,然后在每次访问 B.foo 时创建一个新列表并附加到它。另外,您还有一个问题,即每个子类都必须定义属性以便检索super().foo。如果任何未来的类继承自多个具有 foo 的类,你就会开始很快遇到很多难以理解的问题。
猜你喜欢
  • 2011-11-24
  • 1970-01-01
  • 2021-03-26
  • 2014-04-30
  • 2020-08-01
  • 2011-11-08
  • 1970-01-01
相关资源
最近更新 更多