наследование атрибута класса от суперкласса и более позднего изменения значения для подкласса хорошо работает:
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
Существует ли путь к "глубокой копии" список при наследовании его от суперкласса?
Большое спасибо
Sano
Это не вопрос мелких или глубоких копий, это вопрос ссылок и заданий.
В первом случае Unit.value
и Archer.value
- две переменные, которые ссылаются на одно и то же значение. Когда вы выполняете Archer.value = 5
, вы назначаете новую ссылку на Acher.value.
Чтобы решить вашу проблему, вам необходимо назначить новое значение списка для Archer.list
.
Если эти значения будут доступны только для методов класса, то простейшим решением будет выполнение присваивания при инициализации класса.
Вы можете скопировать список из определения Archer:
class Archer(Unit):
listvalue = Unit.listvalue[:]
Ответ Майкла хорош и прост, но если вы не хотите добавлять эту строку в каждый подкласс 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]
Вы также можете расширить эту идею для автоматического поиска и копирования списков (и 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