Python:类属性(list)的继承

2024-06-01 20:33:03 发布

您现在位置:Python中文网/ 问答频道 /正文

从超级类继承类属性,然后更改子类的值,可以很好地工作:

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
这很好:弓箭手从单位继承价值,但当我改变弓箭手的价值时,单位的价值保持不变。

现在,如果继承的值是一个列表,则浅复制效果会发生,并且超类的值也会受到影响:

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个

从超级类继承列表时,是否有方法“深度复制”该列表?

非常感谢
萨诺


Tags: 列表属性objectvalueunit单位pass子类
3条回答

这不是一个肤浅或深刻的拷贝问题,而是一个参考和分配的问题。

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

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

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

你可以复制阿切尔定义中的列表:

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

Michael的回答很好也很简单,但是如果你不想把这一行添加到每个单元子类中-也许你还有很多类似的列表,元类是解决这个问题的简单方法

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]

您还可以将这个想法扩展到自动查找和复制单元中定义的列表(和dict)

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

相关问题 更多 >