Python: Inheritance of a class attribute (list)
Solution 1
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.
To solve your problem you need to assign a new list value to the 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.
Solution 2
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
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
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
Comments
-
Sano98 almost 2 years
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.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
5Is there a way to "deep copy" a list when inheriting it from the super class?
Many thanks
Sano