Значения переменных экземпляра суперкласса сохраняются в экземплярах подкласса - PullRequest
4 голосов
/ 06 апреля 2011

Я не уверен, является ли это фундаментальным недоразумением с моей стороны, как работает ООП в Python, но я вижу очень странное поведение.Вот фрагмент кода:

class Foo(object):
    def __init__(self, l = []):
        print "Foo1:", l
        self.mylist = l
        print "Foo2:", self.mylist

class Bar(Foo):
    def __init__(self, label=None):

        self.label = label
        super(Bar, self).__init__()
        print "Bar:", self.mylist



bar1 = Bar()
bar1.mylist.append(4)

bar2 = Bar()
print "bar2's list:", bar2.mylist

Я ожидаю, что при построении bar2 переменная экземпляра mylist будет установлена ​​в пустой список.Однако, когда я запускаю эту программу в Python 2.6.6, я получаю следующий вывод:

Foo1: []
Foo2: []
Bar: []
Foo1: [4]
Foo2: [4]
Bar: [4]
bar2's list: [4]

Похоже, что переменная экземпляра mylist Foo сохраняется в нескольких экземплярах класса Bar, но у меня нетИдея, почему это будет.Ребята, любая помощь, которую вы мне могли бы оказать, будет принята с благодарностью.

Ответы [ 2 ]

6 голосов
/ 06 апреля 2011

Проблема в том, что параметры по умолчанию связаны во время инициализации модуля, а не во время вызова функции, поэтому существует только один список по умолчанию, который становится общим по умолчанию для всех вызовов этой функции.

Что вы действительно хотите сделать, это:

def __init__(self, l=None):
    if l is None:
        l = []
    self.mylist = l
2 голосов
/ 06 апреля 2011

Возьмите добычу с Учебник Python по значениям аргументов по умолчанию В нем говорится:

Важное предупреждение: Значение по умолчанию оценивается только один раз.Это имеет значение, когда по умолчанию используется изменяемый объект, такой как список, словарь или экземпляры большинства классов.

или, например, следующая функция накапливает аргументы, передаваемые ей при последующих вызовах:

def f(a, L=[]):
    L.append(a)
    return L

print f(1)
print f(2)
print f(3)

При этом будет напечатано

[1]
[1, 2]
[1, 2, 3]

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

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...