Почему сохраняется значение переменной в функции?

Здраствуйте!
Есть следующий Пайтон-код

bar = []
def foo(bar=[]):
   bar.append(1)
   return bar

print(foo())
print(foo())
print(foo())


output:
[1]
[1, 1]
[1, 1, 1]


Почему при использовании (bar=[]) при вызове функции сохраняются предыдущие значения?
А вот в глобальной переменной ничего не меняется? Тоесть
print(bar)
output:
[]
Как это обьяснить и где о таких нюансах можно почитать? Спасибо!
  • Вопрос задан
  • 2942 просмотра
Решения вопроса 1
Cenness
@Cenness
Комментировать
Пригласить эксперта
Ответы на вопрос 3
@s1dney
дело вот в этой строчке
def foo(bar=[]):
если в функцию не передавать агрумент, то она будет использовать глобальную переменную bar
Ответ написан
Комментировать
@thenno
Проектирую, разрабатываю, преподаю.
Проходил мимо, да и вопрос давно уже закрыт вроде как, но удержаться я не мог. Проблема с областями видимости тут играет важную роль, но тут еще и вступает в ход другая проблема - не нужно бездумно давать значениям по умолчанию изменяемый тип (про это как раз ссылка от @Cenness). Значение по-умолчанию инициализируется только при первом вызове функции. Что это значит? При первом вызове раз мы инициализировали локальный bar пустым списком, затем его изменили. Затем, при втором вызове, локальный bar не инициализируется повторно, а сохраняет свое значение из предыдущего вызова. Таким образом от вызова к вызову мы накапливаем в локальной переменной bar единицы.

Переменная bar в функции будет использована локальная (из строки (def foo(bar=[]):), а не глобальная из строки bar = []. К слову, если запустить код без инициализации глобальной bar:
In [1]: def foo(bar=[]):
   ...:        bar.append(1)
   ...:        return bar
   ...: 

In [2]: print(foo())
[1]

In [3]: print(foo())
[1, 1]

In [4]: print(foo())
[1, 1, 1]

результат будет точно такой же, как и у ТС.


если в функцию не передавать агрумент, то она будет использовать глобальную переменную bar

А это просто новое слово в Python. Если не передавать в функцию аргумент, у которого определено значение по-умолчанию, то и будет использовано значение по-умолчанию. Пример:
In [1]: bar = [1,2,3]

In [2]: def foo(bar=[]):
       bar.append(1)
       return bar
   ...: 

In [3]: foo()
Out[3]: [1]

In [4]: foo()
Out[4]: [1, 1]

In [5]: foo()
Out[5]: [1, 1, 1]

In [6]: foo()
Out[6]: [1, 1, 1, 1]

При первом вызове не наблюдается [1,2,3,1].
Ответ написан
Комментировать
@make_install
Как и было сказано выше - все дело в области видимости. Список bar в глобальной области видимости, а передаваемый в аргументах функции в локальной.

В твоем случае объект bar = [] никак не связан с происходящим в теле функции.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы