Подтвердить что ты не робот

Унаследованная модификация переменной класса в Python

Я хотел бы, чтобы дочерний класс модифицировал переменную класса, которую он наследует от своего родителя.

Я хотел бы сделать что-то вроде:

class Parent(object):
    foobar = ["hello"]

class Child(Parent):
    # This does not work
    foobar = foobar.extend(["world"])

и в идеале:

Child.foobar = ["hello", "world"]

Я мог бы сделать:

class Child(Parent):
    def __init__(self):
      type(self).foobar.extend(["world"])

но затем каждый раз, когда я создаю экземпляр Child, в список добавляется "мир", что нежелательно. Я мог бы изменить его дальше:

class Child(Parent):
    def __init__(self):
      if type(self).foobar.count("world") < 1:
          type(self).foobar.extend(["world"])

но это все равно хак, потому что я должен создать экземпляр Child до того, как он сработает.

Есть ли лучший способ?

4b9b3361

Ответ 1

Предполагая, что вы хотите иметь отдельный список в подклассе, не изменяйте список родительских классов (что кажется бессмысленным, поскольку вы можете просто изменить его на месте или поместить туда ожидаемые значения):

class Child(Parent):
    foobar = Parent.foobar + ['world']

Обратите внимание, что это работает независимо от наследования, что, вероятно, хорошо.

Ответ 2

Вы не должны использовать изменяемые значения в переменных класса. Задайте такие значения в экземпляре вместо этого, используя инициализатор экземпляра __init__():

class Parent(object):
    def __init__(self):
        self.foobar = ['Hello']

class Child(Parent):
    def __init__(self):
        super(Child, self).__init__()
        self.foobar.append('world')

В противном случае происходит то, что список foobar используется не только для экземпляров, но и для подклассов.

В любом случае вам придется избегать модификации mutables родительских классов, даже если вы хотите разделить состояние между экземплярами с помощью переменной переменной; только присваивание имени создало бы новую переменную:

class Parent(object):
    foobar = ['Hello']

class Child(Parent):
    foobar = Parent.foobar + ['world']

где новая переменная foobar создается для класса Child. Используя назначение, вы создали новый экземпляр списка, а переменная Parent.foobar изменена.

Соблюдайте осторожность с вложенными переменными в таких случаях; используйте модуль copy, чтобы при необходимости создать глубокие копии.