Python: наследование атрибута класса (список) - PullRequest
5 голосов
/ 21 марта 2010

наследование атрибута класса от суперкласса и последующее изменение значения для подкласса работает нормально:

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, но когда я изменяю значение 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

Есть ли способ "глубокого копирования" списка при наследовании его от суперкласса?

Большое спасибо
Сано

Ответы [ 3 ]

13 голосов
/ 21 марта 2010

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

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

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

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

7 голосов
/ 21 марта 2010

Ответ Майкла приятный и простой, но если вы хотите избежать добавления этой строки в каждый подкласс 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]

Вы также можете расширить эту же идею для автоматического поиска и копирования списков (и диктов), определенных в Единице

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
0 голосов
/ 21 марта 2010

Вы можете скопировать список в определении Арчера:

class Archer(Unit):
    listvalue = Unit.listvalue[:]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...