San*_*o98 5 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
Run Code Online (Sandbox Code Playgroud)
导致输出:
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
Run Code Online (Sandbox Code Playgroud)
产量:
10
10
5
5
从超类继承列表时,有没有办法"深度复制"列表?
非常感
谢佐诺
mik*_*obi 13
这不是浅层或深层复制的问题,而是引用和分配的问题.
它是第一种情况Unit.value,Archer.value是引用相同值的两个变量.执行此操作时Archer.value = 5,您将为Acher.value分配新引用.
要解决您的问题,您需要为其分配一个新的列表值Archer.list.
如果这些值只能通过类方法访问,那么最简单的解决方案是在初始化类时进行赋值.
迈克尔的答案很简单,但是如果你想避免将这一行添加到每个单元的子类中 - 也许你有一堆其他的列表,那么元类就是一种解决问题的简单方法
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
Run Code Online (Sandbox Code Playgroud)
输出:
[10]
[10]
[10]
[5]
Run Code Online (Sandbox Code Playgroud)
您还可以扩展同样的想法,以自动查找和复制Unit中定义的列表(和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
Run Code Online (Sandbox Code Playgroud)