Как работает передача аргументов в функции в Python: по ссылке или по значению
Что проверяют
Понимаете ли, что дихотомия «по ссылке или по значению» к Python неприменима, и умеете ли предсказывать поведение через изменяемость объекта и факт переприсваивания имени.
Как отвечать
Модель памяти. В Python нет переменных-ячеек, есть имена, привязанные к объектам. При вызове формальный параметр становится ещё одним именем того же объекта. Такую схему называют передачей по ссылке на объект, call by object reference или call by sharing.
Следствие ровно одно. Функция не может переприсвоить переменную вызывающего кода, но может изменить сам объект, если тот изменяемый.
def rebind(x):
x = [9] # перепривязка локального имени
def mutate(x):
x.append(9) # изменение самого объекта
lst = [1]
rebind(lst); print(lst) # [1]
mutate(lst); print(lst) # [1, 9]rebind доказывает, что это не передача по ссылке в смысле C++ или Pascal: там присваивание внутри функции меняло бы переменную снаружи.
Неизменяемые типы (int, str, tuple, frozenset) ведут себя так же, просто изменить их нечем. x += 1 для числа создаёт новый объект и перепривязывает локальное имя, оригинал остаётся прежним.
Тонкость, на которой ловят. У списка += это __iadd__, то есть мутация на месте, и снаружи её видно. А lst = lst + [4] создаёт новый список и меняет только локальное имя. Внешне похожий код даёт разный результат:
def a(lst): lst += [4] # снаружи видно
def b(lst): lst = lst + [4] # снаружи не видноПрактические выводы:
- Не мутировать входные аргументы молча. Либо возвращать новый объект, либо явно называть функцию
sort_in_place,update_config. - Изменяемый объект в значении по умолчанию (
def f(items=[])) создаётся один раз при определении функции и живёт между вызовами. Правильноdef f(items=None)и создание внутри. - Если нужно защитить данные вызывающего, копировать явно:
list(x),dict(x),copy.deepcopyдля вложенных структур.
Где спотыкаются
Отвечают формулой «изменяемые передаются по ссылке, неизменяемые по значению». Механизм передачи одинаков для всех типов, разница только в том, можно ли объект изменить на месте, и именно эту разницу интервьюер и хочет услышать сформулированной точно.