7

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

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

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

非常感谢
佐野

4

3 回答 3

15

这不是浅拷贝或深拷贝的问题,而是引用和分配的问题。

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

要解决您的问题,您需要为Archer.list.

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

于 2010-03-21T19:13:49.723 回答
8

迈克尔的回答很好也很简单,但是如果您希望避免将该行添加到每个 Unit 子类 - 也许您有一堆类似的其他列表,元类是解决问题的简单方法

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]

您还可以扩展这个相同的想法来自动查找和复制 Unit 中定义的列表(和字典)

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
于 2010-03-21T20:34:17.033 回答
0

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

class Archer(Unit):
    listvalue = Unit.listvalue[:]
于 2010-03-21T19:14:33.760 回答