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
这没问题:弓箭手(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
有没有办法在从父类继承列表时进行“深拷贝”?
非常感谢
Sano
3 个回答
1
你可以在弓箭手的定义里复制这个列表:
class Archer(Unit):
listvalue = Unit.listvalue[:]
10
Michael的回答简单明了,但如果你想避免在每个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
18
这不是关于浅拷贝或深拷贝的问题,而是关于引用和赋值的问题。
在第一个例子中,Unit.value
和 Archer.value
是两个变量,它们指向同一个值。当你执行 Archer.value = 5
时,你实际上是给 Archer.value
赋了一个新的值。
要解决你的问题,你需要给 Archer.list
赋一个新的列表值。
如果这些值只是通过类的方法来访问,那么最简单的解决办法是在类初始化的时候进行赋值。