Передача аргументов и lambda

Частый спорный вопрос: Python передаёт аргументы по значению или по ссылке? И зачем нужны lambda.

Python использует передачу по ссылке на объект (call by object reference): в функцию попадает ссылка на тот же объект, но переприсваивание имени внутри функции наружу не видно.

Вопрос: по ссылке или по значению?

Чёткий ответ. Ни то, ни другое в чистом виде. Функция получает ссылку на объект. Если объект изменяемый и вы меняете его на месте — изменение видно снаружи. Если вы переприсваиваете имя внутри — снаружи ничего не меняется.

def modify_list(lst):
    lst.append(99)        # меняем объект на месте — видно снаружи

def reassign(lst):
    lst = [0, 0, 0]       # переприсваиваем локальное имя — наружу не видно

def modify_int(n):
    n += 100              # int неизменяем — создаётся новый объект

data = [1, 2, 3]
modify_list(data)
print("после modify_list:", data)
reassign(data)
print("после reassign:   ", data)

num = 5
modify_int(num)
print("после modify_int: ", num)

Вывод:

после modify_list: [1, 2, 3, 99]
после reassign:    [1, 2, 3, 99]
после modify_int:  5

modify_list изменил объект на месте — снаружи видно. reassign просто переназначил локальное имя — оригинал не тронут. modify_int работает с неизменяемым числом, поэтому снаружи num остался 5.

lambda: анонимная функция-выражение

lambda — короткая функция из одного выражения без имени. Полезна там, где функция нужна «на один раз»: ключ сортировки, аргумент map/filter.

square = lambda x: x * x
print(square(5))

people = [("Аня", 30), ("Боб", 25), ("Ева", 35)]
by_age = sorted(people, key=lambda p: p[1])
print(by_age)

Вывод:

25
[('Боб', 25), ('Аня', 30), ('Ева', 35)]

Когда lambda, а когда def

  • lambda — для короткого выражения, передаваемого как аргумент (ключ сортировки, колбэк).
  • def — когда есть имя, несколько строк, документация или ветвления.
words = ["banana", "kiwi", "apple", "fig"]
print(sorted(words, key=lambda w: len(w)))   # по длине
print(sorted(words, key=len))                # то же без lambda — функция уже есть

Вывод:

['fig', 'kiwi', 'apple', 'banana']
['fig', 'kiwi', 'apple', 'banana']

Итог

  • Python передаёт ссылку на объект: правка mutable на месте видна снаружи, переприсваивание — нет.
  • Неизменяемые аргументы (числа, строки) функция «изменить» не может.
  • lambda — короткая безымянная функция-выражение для одноразового использования.
Проверьте себя
1. Что увидит вызывающий код после функции, которая делает lst.append(99)?
AИзменение видно — список общий
BИзменение не видно
CОшибку
DСписок станет None
2. Почему modify_int(num) с n += 100 не меняет num снаружи?
Aint передаётся копией байтов
Bint неизменяем: n += 100 создаёт новый объект, имя снаружи не трогается
CЭто баг
DНужно вернуть значение через global
3. Для чего обычно используют lambda?
AДля многострочных функций с документацией
BКак короткое выражение-аргумент, например ключ сортировки
CДля определения классов
DДля импорта модулей
Поддержать проект