【问题标题】:Class attribute overriding: keep parent class changes类属性覆盖:保持父类变化
【发布时间】:2025-12-12 09:55:02
【问题描述】:

我想要两节课。具有默认类属性的 A 类和覆盖该类属性的 B 类(子类)。但是如果A类属性定义被developper修改了,我不想再写B类属性了。

示例:使用简单覆盖:

class Animal:
    actions = {}

class Dog(Animal):
    actions = {'bite': 1}

如果一天,Animal 修改如下:

class Animal:
    actions = {'bleed': 1}

狗类必须重写。所以我这样做是为了防止父类更新:

Python 3.4.0 (default, Apr 11 2014, 13:05:18) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:
...   d = {}
...   @classmethod
...   def c(cls):
...     print(cls.d)
... 
>>> class B(A):
...   d = A.d.copy()
...   d.update({0: 1})
... 
>>> B.c()
{0: 1}
>>> A.c()
{}

这是一个好方法吗?还是有更“python 方式”来做到这一点?

【问题讨论】:

  • 你永远不会改变广告
  • 类属性重载到底是什么意思?
  • 考虑到你的问题,我重写了问题。
  • 您可能会发现这个关于在 python 中调用父类构造函数的链接很有用。 *.com/questions/2399307/…

标签: python


【解决方案1】:

类方法中的属性复制

通过使用copy,您可以确保Ad,无论是什么/谁定义了它,都将是B 扩展它之前的起点。

class A:
    d = {}
    @classmethod
    def c(cls):
        print (cls.d)

class B(A):
    d = A.d.copy()
    d.update({0:1})

B.c()
A.c()

输出

{0: 1}
{}

开发者稍后更改AB 得到A 而无需触及B 的定义。

class A:
    d = {2:3}
    @classmethod
    def c(cls):
        print (cls.d)

class B(A):
    d = A.d.copy()
    d.update({0:1})

B.c()
A.c()

输出

{0: 1, 2: 3}
{2: 3}

警告: 如果d 中包含其他对象,您可能需要使用copy.deepcopy,否则只会复制第一个“级别”,所有其他对象都将引用原创(在我知道之前,这曾让我很多感到悲伤!)。

在实例方法中继承

字典复制是pythonic,因为很明显B 得到A 并对其进行扩展,但是由于您可能会在您的用例中创建实例(例如Dog),这些类可能通过使用__init__ 方法来忽略class instance 的概念。这将允许您拥有多个 Bs 和可能唯一的 ds。

这是一个考虑到实例的类定义示例

class A:
    def __init__(self):
        self.d = {}
    def c(self):
        print (self.d)

class B(A):
    def __init__(self):
        A.__init__(self)
        self.d.update({0:1})

# create instances of each class
a = A()
b1 = B() 
b2 = B()  

# call each instance's c method
b1.c()
b2.c()
a.c()

# you can even update on the fly without affecting the other!
a.d.update({2:3})
b1.d.update({4:5})
b2.d.update({7:8})
b1.c()
b2.c()
a.c()

输出

{0: 1}
{0: 1}
{}
{0: 1, 4: 5}
{0: 1, 7: 8}
{2: 3}

【讨论】: