Кожен, хто поводився з Python досить довго, був покусаний (або розірваний на частини) наступним номером:
def foo(a=[]):
a.append(5)
return a
Python послушники б очікувати ця функція завжди повертає список тільки з одним елементом: [5]
. Натомість результат настільки різний і вражаючий (для новачків):
>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
>>> foo()
[5, 5, 5, 5]
>>> foo()
Один мій менеджер одного разу вперше зіткнувся з цією особливістю і назвав це "драматичним недоліком дизайну" мови. Я відповів, що поведінка має основне пояснення, і це справді дуже спантеличено і несподівано, якщо ви не розумієте внутрішніх справ. Однак я не зміг відповісти (на себе) на таке питання: що є причиною прив'язки аргументу за замовчуванням при визначенні функції, а не при виконанні функції? Я сумніваюсь, що досвідчене поведінка має практичне використання (хто реально використовував статичні змінні в С, без розмноження помилок?)
Редагувати :
Бацек зробив цікавий приклад. Разом з більшістю ваших коментарів і зокрема Utaal, я детально розробив:
>>> def a():
... print("a executed")
... return []
...
>>>
>>> def b(x=a()):
... x.append(5)
... print(x)
...
a executed
>>> b()
[5]
>>> b()
[5, 5]
Мені здається, що проектне рішення було відносно того, куди поставити область параметрів: всередині функції або "разом" з нею?
Виконання прив'язки всередині функції означало б, що x
фактично прив'язане до вказаного за замовчуванням, коли функція викликається, а не визначена, щось, що представлятиме глибокий недолік: def
лінія буде "гібридною" в тому сенсі, що частина зв'язування (з об'єкт функції) відбуватиметься при визначенні, а частина (призначення параметрів за замовчуванням) під час виклику функції.
Фактична поведінка є більш послідовною: все в цьому рядку оцінюється при виконанні цього рядка, тобто при визначенні функції.
[5]
" Я новачок Python, і я цього не очікував, бо, очевидно foo([1])
, повернеться [1, 5]
, ні [5]
. Що ви хотіли сказати, це те, що новачок очікує, що функція, яка називається без параметра , завжди повернеться [5]
.