我在python中有这个通用问题。基类定义了类属性class_attr
。此属性是不可变的,在这种情况下它是一个数字。我想从派生类更改此属性,从而将Base.class_attr
重新绑定到新值(在我的玩具案例中,递增它)。
问题是如何在声明Base
中没有明确命名Base.class_attr += 1
的情况下执行此操作。
class Base(object):
# class attribute:
class_attr = 0
class Derived(Base):
@classmethod
def increment_class_attr(cls):
Base.class_attr += 1
# is there a solution which does not name the owner of the
# class_attr explicitly?
# This would cause the definition of Derived.class_attr,
# thus Base.class_attr and Derived.class_attr would be
# two independent attributes, no more in sync:
# cls.class_attr += 1
Derived.increment_class_attr()
Derived.increment_class_attr()
print Base.class_attr # 2
请注意:我正在回答这个问题,也就是说,我可以重新绑定父类的属性。我不是在解决这个问题的解决办法之后(例如,将increment_class_attr
转移到Base)。
答案 0 :(得分:1)
使用__bases__
属性:
In [68]: class Base(object):
...: # class attribute:
...: class_attr = 0
...:
In [69]: class Derived(Base):
...: @classmethod
...: def inc(cls):
...: p, = cls.__bases__
...: p.class_attr += 1
...:
In [70]: Base.class_attr
Out[70]: 0
In [71]: Derived.inc()
In [72]: Derived.inc()
In [73]: Base.class_attr
Out[73]: 2
如果您有多重继承:
In [88]: class DifferentInherited(object):
...: class2_attr = 0
...:
In [90]: class Der2(Base, DifferentInherited):
...: @classmethod
...: def inc(cls):
...: print cls.__bases__
...: a, b, = cls.__bases__
...: print a.class_attr
...: print b.class2_attr
...:
In [91]: Der2.inc()
(<class '__main__.Base'>, <class '__main__.DifferentInherited'>)
2
0
假设您不知道继承顺序,则需要测试每个类的变量:
In [127]: class Der3(DifferentInherited, Base):
...: @classmethod
...: def inc(cls):
...: # This gets a list of *all* classes with the attribute `class_attr`
...: classes = [c for c in cls.__bases__ if 'class_attr' in c.__dict__]
...: for c in classes:
...: c.class_attr += 1
...:
In [128]: Der3.inc()
In [129]: Base.class_attr
Out[129]: 3
In [131]: DifferentInherited.class2_attr
Out[131]: 0
多重继承使用__mro__
:
In [146]: class Multi(Der3):
...: @classmethod
...: def inc(cls):
...: c_attr = [c for c in cls.__mro__ if 'class_attr' in c.__dict__]
...: print c_attr
...: c_attr[0].class_attr += 1
...:
In [147]: Multi.inc()
[<class '__main__.Base'>]
In [148]: Base.class_attr
Out[148]: 4