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
который является очень хорошо: Стрелец наследовал значение от Единицы, но когда я изменяю значение Стрельца, значение Единицы остается нетронутым.

Теперь, если наследованное значение является списком, мелкие забастовки эффекта копии и значение суперкласса также затронут:

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

5
задан Sano98 21 March 2010 в 19:00
поделиться

3 ответа

Это не вопрос мелких или глубоких копий, это вопрос ссылок и заданий.

В первом случае Unit.value и Archer.value - две переменные, которые ссылаются на одно и то же значение. Когда вы выполняете Archer.value = 5 , вы назначаете новую ссылку на Acher.value.

Чтобы решить вашу проблему, вам необходимо назначить новое значение списка для Archer.list .

Если эти значения будут доступны только для методов класса, то простейшим решением будет выполнение присваивания при инициализации класса.

13
ответ дан 18 December 2019 в 07:53
поделиться

Вы можете скопировать список из определения Archer:

class Archer(Unit):
    listvalue = Unit.listvalue[:]
0
ответ дан 18 December 2019 в 07:53
поделиться

Ответ Майкла хорош и прост, но если вы не хотите добавлять эту строку в каждый подкласс 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
7
ответ дан 18 December 2019 в 07:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: