Вопрос с собеседования · Python

Как передаются аргументы в функцию — по значению или по ссылке?

JuniorФункции
Ещё спрашивают так:
  • Передача параметров в Python по ссылке или по значению?
  • Может ли функция изменить переданный ей список?
Коротко

Ни то ни другое в классическом смысле: передаётся ссылка на объект (call by sharing).

  • Изменяемый объект функция может поменять — изменение видно снаружи
  • Переприсвоение параметра внутри функции снаружи не видно

А ещё Если менять аргумент не нужно — копируйте или возвращайте новый объект

Подробно

При вызове f(x) параметр функции становится ещё одним именем для того же объекта, на который указывает x. Объект не копируется.

Поэтому:

  • если функция меняет объект (lst.append(1), d["k"] = v), вызывающий код увидит изменение — это тот же объект;
  • если функция переприсваивает параметр (lst = [1, 2]), она лишь привязывает своё локальное имя к новому объекту; снаружи ничего не меняется;
  • для неизменяемых объектов (числа, строки, кортежи) «изменить» можно только переприсваиванием, поэтому снаружи их не поменять никогда.

Это иногда называют «передача по значению ссылки» или call by sharing. В отличие от C++ ссылок, функция не может заставить внешнюю переменную указывать на другой объект.

Хорошая практика — не менять аргументы молча. Либо функция явно «изменяет на месте» (как list.sort, возвращает None), либо возвращает новый объект (как sorted).

Пример

def mutate(lst):
    lst.append(99)        # меняем объект

def rebind(lst):
    lst = [0]             # меняем только локальное имя

data = [1, 2]
mutate(data)
print(data)               # [1, 2, 99]
rebind(data)
print(data)               # [1, 2, 99] — не изменилось

Что хотят услышать

  • Передаётся ссылка на объект, копирования нет.
  • Различие между изменением объекта и переприсвоением имени.
  • Поведение для изменяемых и неизменяемых типов.

Частые ошибки

  • Ответ «по ссылке» без оговорки про переприсвоение.
  • Ответ «по значению, объект копируется».

Проверьте себя

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✓Передаётся ссылка на объект: изменение объекта видно снаружи, переприсвоение параметра — нет
  • ✗Передача по ссылке, как в C++: присваивание параметру внутри функции меняет переменную вызывающего
  • ✗Всегда передаётся копия объекта, поэтому снаружи ничего не меняется
  • ✗Списки передаются по значению, числа — по ссылке

Что спросят дальше

Разбор темы

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.

Разбор собеседования