Python:类属性的继承(列表)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2488306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python: Inheritance of a class attribute (list)
提问by Sano98
inheriting a class attribute from a super class and later changing the value for the subclass works fine:
从超类继承类属性,然后更改子类的值工作正常:
class Unit(object):
value = 10
class Archer(Unit):
pass
print Unit.value
print Archer.value
Archer.value = 5
print Unit.value
print Archer.value
leads to the output:
10
10
10
5
which is just fine: Archer inherits the value from Unit, but when I change Archer's value, Unit's value remains untouched.
导致输出:
10
10
10
5
这很好:Archer 继承了 Unit 的值,但是当我更改 Archer 的值时,Unit 的值保持不变。
Now, if the inherited value is a list, the shallow copy effect strikes and the value of the superclass is also affected:
现在,如果继承的值是一个列表,浅拷贝效果就会发生,超类的值也会受到影响:
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
Output:
10
10
5
5
输出:
10
10
5
5
Is there a way to "deep copy" a list when inheriting it from the super class?
从超类继承列表时,有没有办法“深度复制”列表?
Many thanks
Sano
非常感谢
佐野
回答by mikerobi
It is not a matter of shallow or deep copies, it is a matter of references and assignments.
这不是浅拷贝或深拷贝的问题,而是引用和赋值的问题。
It the first case Unit.value
and Archer.value
are two variables which reference the same value. When you do Archer.value = 5
, you are assigning a new reference to Acher.value.
它是第一种情况,Unit.value
并且Archer.value
是引用相同值的两个变量。当您这样做时Archer.value = 5
,您正在为 Acher.value 分配一个新的引用。
To solve your problem you need to assign a new list value to the Archer.list
.
要解决您的问题,您需要为Archer.list
.
If these values are only going to be accessed by class methods, then the simplest solution is to do the assignment when the class is initialized.
如果这些值只能由类方法访问,那么最简单的解决方案是在类初始化时进行赋值。
回答by John La Rooy
Michael's answer is nice and simple, but if you wish to avoid having to add that line to each Unit subclass - maybe you have a bunch of other lists like that one, a metaclass is an easy way to solve the problem
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
output:
输出:
[10]
[10]
[10]
[5]
You can also extend this same idea to automatically find and copy up lists (and dicts) defined in Unit
您还可以扩展相同的想法以自动查找和复制 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
回答by Michael Williamson
You coud copy the list in the definition of Archer:
您可以复制 Archer 定义中的列表:
class Archer(Unit):
listvalue = Unit.listvalue[:]