Python:类属性的继承(列表)

时间:2010-03-21 19:00:56

标签: python inheritance list deep-copy class-attributes

继承超类的类属性,稍后更改子类的值可以正常工作:

class Unit(object):
    value = 10

class Archer(Unit):
    pass

print Unit.value
print Archer.value

Archer.value = 5

print Unit.value
print Archer.value

导致输出:
10个
10个
10个
5
这很好:Archer继承了Unit的值,但是当我改变Archer的值时,Unit的值仍然保持不变。

现在,如果继承的值是列表,则浅拷贝效果会发生,超类的值也会受到影响:

class Unit(object):
    listvalue = [10]

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

输出:
10个
10个
5
5

从超类继承列表时,有没有办法“深度复制”列表?

非常感谢 佐野

3 个答案:

答案 0 :(得分:13)

这不是浅层或深层复制的问题,而是引用和分配的问题。

第一种情况Unit.valueArcher.value是两个引用相同值的变量。当您执行Archer.value = 5时,您正在为Acher.value分配新的引用。

要解决您的问题,您需要为Archer.list分配新的列表值。

如果这些值只能通过类方法访问,那么最简单的解决方案是在初始化类时进行赋值。

答案 1 :(得分:7)

迈克尔的答案很简单,但是如果你想避免将这一行添加到每个单元的子类中 - 也许你有一堆其他的列表,那么元类是一种解决问题的简单方法

class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        self.listvalue = [10]

class Unit(object):
    __metaclass__ = UnitMeta
    pass

class Archer(Unit):
    pass

print Unit.listvalue
print Archer.listvalue

Archer.listvalue[0] = 5

print Unit.listvalue
print Archer.listvalue

输出:

[10]
[10]
[10]
[5]

您还可以扩展同样的想法,以自动查找和复制在单元

中定义的列表(和dicts)
class UnitMeta(type):
    def __init__(self, *args):
        super(UnitMeta, self).__init__(*args)
        for superclass in self.__mro__:
            for k,v in vars(superclass).items():
                if isinstance(v, (list, dict, )):
                    setattr(self, k, type(v)(v))

class Unit(object):
    __metaclass__ = UnitMeta
    listvalue = [10]

class Archer(Unit):
    pass

答案 2 :(得分:0)

您可以复制Archer定义中的列表:

class Archer(Unit):
    listvalue = Unit.listvalue[:]