Предположим, что у Вас есть что-то вроде этого:
class intlist:
def __init__(self,l = []):
self.l = l
def add(self,a):
self.l.append(a)
def appender(a):
obj = intlist()
obj.add(a)
print obj.l
if __name__ == "__main__":
for i in range(5):
appender(i)
Функция создает экземпляр intlist и обращается к этому новому экземпляру, который метод добавляет на l атрибута экземпляра.
Как прибывает, вывод этого кода:
[0]
[0, 1]
[0, 1, 2]
[0, 1, 2, 3]
[0, 1, 2, 3, 4]
? Если я переключаюсь
obj = intlist()
с
obj = intlist(l=[])
Я получаю желаемый вывод
[0]
[1]
[2]
[3]
[4]
Почему это происходит?
Спасибо
А, вы столкнулись с одной из распространенных проблем Python: значения по умолчанию вычисляются один раз, а затем используются повторно. Поэтому каждый раз, когда вызывается __init__
, используется тот же самый список.
Это Pythonic способ сделать то, что вы хотите:
def __init__(self, l=None):
self.l = [] if l is None else l
Для получения дополнительной информации ознакомьтесь с документацией Python (особенно с тремя абзацами после этого заголовка).
Редактировать: гораздо лучшее описание есть в другом ответе.
Когда вы устанавливаете значение по умолчанию l=[]
в __init__
, вы фактически используете один и тот же список каждый раз. Вместо этого вы можете попробовать что-то вроде:
class intlist:
def __init__(self, l=None):
if l is None:
self.l = []
else:
self.l = l
Проблема в том, что когда вы говорите
def __init__(self,l = []):
Вы говорите Python использовать один и тот же список, []
, для каждого вызова конструктора. Поэтому при каждом вызове obj = intlist()
будет добавляться один и тот же список.
Вместо этого следует установить l
в значение по умолчанию None
, которое является скаляром (поэтому ваш код будет работать как ожидается, если оно будет использоваться много раз). Затем, если l
равно None
, инициализируйте новый член класса как []
. В противном случае просто присвойте переменную-член l
.
Будьте осторожны с параметрами по умолчанию таких типов, как списки и dicts. Каждый экземпляр intlist получает один и тот же объект списка из параметра по умолчанию.
Для получения дополнительной информации я предлагаю прочитать это: http://effbot.org/zone/default-values.htm
obj = intlist ()
вызывает вашу функцию __ init __ ()
, которая использует один и тот же массив для каждого экземпляра класса.
obj = intlist (l = [])
создает новый массив для каждого экземпляра.
Такое поведение происходит потому, что все вызовы вашего метода __init__
имеют один и тот же список по умолчанию.
Попробуйте:
class intlist:
def __init__(self, l):
self.l = l if (l is not None) else []
def add(self,a):
self.l.append(a)
EDIT: Используйте is not
, согласно SilentGhost