我想在一些类的所有实例和它的所有派生类之间共享一些信息.
class Base():
cv = "some value" # information I want to share
def print_cv(self, note):
print("{}: {}".format(note, self.cv))
@classmethod
def modify_cv(cls, new_value):
# do some class-specific stuff
cls.cv = new_value
class Derived(Base):
pass
b = Base()
d = Derived()
b.print_cv("base")
d.print_cv("derived")
输出是预期的(两个类的实例都看到正确的类属性):
base: some value
derived: some value
我可以更改此类属性的值,一切都很好:
# Base.cv = "new value"
b.modify_cv("new value")
b.print_cv("base") # -> base: new value
d.print_cv("derived") # -> derived: new value
到现在为止还挺好.问题是如果我通过派生类访问cv,Base和派生类之间的“连接”可以被破坏:
# Derived.cv = "derived-specific value"
d.modify_cv("derived-specific value")
b.print_cv("base") # -> base: new value
d.print_cv("derived") # -> derived: derived-specific value
这种行为是预料之中的,但这不是我想要的!
我理解为什么a和b看到不同的cv值 – 因为它们是不同类的实例.我在派生类中重写了cv值,现在派生类的行为有所不同,我已多次使用此功能.
但对于我目前的任务,我需要a和b总是使用相同的cv!
UPDATE
我已经更新了问题,现在它更好地描述了现实生活中的情况.其实我没有像这样修改cv值:
Base.cv = "new value"
修改是在一些类方法中完成的(实际上所有这些类方法都是在Base类中实现的).
现在解决方案变得明显,我只需稍微修改一下方法:
class Base():
@classmethod
def modify_cv(cls, new_value):
#cls.cv = new_value
Base.cv = new_value
谢谢大家的讨论和想法(在开始时我将使用getter / setter和module-level属性)
最佳答案 当您需要知道哪个类正在调用该方法时,classmethod很有用,但如果您想要相同的行为而不管调用该方法的类,则可以使用staticmethod.然后,您可以使用Base.cv通过基类的名称访问类变量:
class Base:
cv = "some value" # information I want to share
def print_cv(self, note):
print("{}: {}".format(note, self.cv))
@staticmethod
def modify_cv(new_value):
Base.cv = new_value
您仍然可以在任何实例或子类上调用它,但它总是更改Base.cv:
>>> b = Base()
>>> d = Derived()
>>> Base.cv == Derived.cv == b.cv == d.cv == "some value"
True
>>> d.modify_cv("new value")
>>> Base.cv == Derived.cv == b.cv == d.cv == "new value"
True
更新:
如果由于其他原因仍然需要访问该类,请像以前一样使用带有cls参数的classmethod,但仍然通过Base.cv而不是cls.cv访问基类的变量:
@classmethod
def modify_cv(cls, new_value):
do_stuff_with(cls)
Base.cv = new_value