Вопрос

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

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

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

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

Это было полезно?

Решение

Дело не в мелких или глубоких копиях, а в ссылках и назначениях.

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

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

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

Другие советы

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

Вы также можете расширить эту идею, чтобы автоматически находить и копировать списки (и словари), определенные в 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

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

class Archer(Unit):
    listvalue = Unit.listvalue[:]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top