python - Python:如何在派生类之间共享类属性?
问题描述
我想在某个类的所有实例和它的所有派生类之间共享一些信息。
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
:
# 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
!
更新
我已经更新了这个问题,现在它更好地描述了现实生活中的情况。实际上我没有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 和模块级属性)
解决方案
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
更新:
如果由于其他原因仍需要访问该类,请像以前一样使用参数,但仍通过而不是访问基类classmethod
的变量:cls
Base.cv
cls.cv
@classmethod
def modify_cv(cls, new_value):
do_stuff_with(cls)
Base.cv = new_value
推荐阅读
- visual-studio-code - 在 Visual Studio Code 中运行自定义命令作为运行配置
- amazon-web-services - 如何将我的域与我的 AWS Lightsail 容器服务一起使用?
- python - 将图片上传到谷歌驱动器而不提醒用户
- testing - 如何连续运行线程组,然后在 jmeter 中再次启动相同的循环
- python-3.x - 如何列出单词最多的一行中的单词数?
- arrays - 将 NUMBER 的 Oracle RAW 转换为 .NET Int64
- reactjs - 在水平条反应图表js 2的末尾显示文本
- bash - 为什么有和没有 * 在 Bash 中有所不同
- python-3.x - 如何在 python/pandas 中读取这个分号分隔的数据文件?
- javascript - 使用 spawnSync 和 CUPS 命令行的 EACCES 错误