Проходил мимо, да и вопрос давно уже закрыт вроде как, но удержаться я не мог. Проблема с областями видимости тут играет важную роль, но тут еще и вступает в ход другая проблема - не нужно бездумно давать значениям по умолчанию изменяемый тип (про это как раз ссылка от
@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].