Небезпечні змінні об’єкти як значення аргументів функції за замовчуванням
Якось пишу я один сайт (та все той же) і натикаюсь на отаку грізну помилку:
Через деякий час знайшлась і причина помилки, і те падло яке цю причину написало:
Bunyk Fri Oct 07 13:45 2011: def __init__(self, label=u'', validators=[ Bunyk Fri Oct 07 18:31 2011: validators.NumberRange(min=decimal.Decimal('0.01'), Bunyk Fri Oct 07 13:45 2011: message=_(u"Значение должно быть больше чем %(min)s")) Bunyk Fri Oct 07 13:45 2011: ], **kwargs Bunyk Fri Oct 07 13:45 2011: ):
Ну справді, хто так пише. Дужку варто закривати на тому ж рівні вкладеності на якому вона відкривалась це раз:
def __init__(self, label=u'', validators=[validators.NumberRange( min=decimal.Decimal('0.01'), message=_(u"Значение должно быть больше чем %(min)s") )], **kwargs ):
І два – списки, словники та інші змінні (mutable) об’єкти не надто бажані як значення аргументів за замовчуванням.
Чому так? Тому що це уможливлює ефекти про які я зараз розповім. А ці ефекти можуть здивувати, як і повідомлення на картинці.
Як відомо, в Python все є об’єктом. Навіть функції і класи. А про будь-який об’єкт найважливіше що варто знати – це коли і як він створюється.
Тепер давайте розглянемо який-небудь сферичний код в вакуумі. Наприклад такий:
def next(line=[]): line.append(len(line) + 1) print line next() # OUT: [1] next() # OUT: [1, 2] next() # OUT: [1, 2, 3] next(range(10)) # OUT: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11] next() # OUT: [1, 2, 3, 4] next(line=[]) # OUT: [1] next() # OUT: [1, 2, 3, 4, 5]
Так от, щоб зрозуміти чому він так поводиться, варто знати, що змінні (і аргументи функцій) в Python це насправді не значення а посилання. А []
– конструктор порожнього списку.
В першому рядку коду створюється об’єкт функції, разом з ним створюється об’єкт списку, і стандартним значенням параметра функції призначається посилання на цей список.
Можливий варіант переписування коду так щоб він працював більш “очікувано”:
def next(line=None): if not line: line = [] line.append(len(line) + 1) print line
Ну а зараз строгостатичні чистолямбдасамці можуть срати цеглою нижче. 😉
>>> Ну а зараз строгостатичні чистолямбдасамці можуть срати цеглою нижче.
а тут таких немає ) код кул =)
danbstt
22 Березня, 2012 at 23:36
Дивно. Це ж величезне жахіття змінного стану. 🙂 Гірше тільки змінний стан в конкурентному середовищі.
bunyk
27 Березня, 2012 at 23:49
А от і є.
Max Ulidtko
28 Березня, 2012 at 15:19