Глава 13 · Автоматизация с помощью функций

Изменяемые и неизменяемые аргументы

Один из самых важных уроков главы: присваивание параметру и мутация объекта, на который он указывает, — это два совершенно разных действия.

Неизменяемый аргумент: rebinding не выходит наружу

immutable_argument.py
def add_one(number):
    number += 1
    print(number)

x = 10
add_one(x)
print(x)
11
10
add_one(x) печатает 11, но x снаружи остался 10
x10
До вызова: x → 10
x10number11
Внутри add_one: number += 1 привязывает number к НОВОМУ объекту 11 — x это не затрагивает
Не «функция получает копию x»
Точнее: number сначала указывает туда же, куда и x (на 10). Но number += 1 — это number = number + 1: создаётся НОВЫЙ объект 11, и number начинает указывать на него. x по-прежнему указывает на старый объект 10 — они разошлись.

Изменяемый аргумент: мутация видна снаружи

mutable_argument.py
def add_item(items):
    items.append("Python")

skills = ["Git"]
add_item(skills)
print(skills)
['Git', 'Python']
skills изменился, хотя мы вызвали функцию, а не присвоили skills напрямую
skills (снаружи)items (параметр)['Git','Python']
skills и items — два имени ОДНОГО списка; items.append(...) меняет его для обоих
Это не магия — это тот же aliasing из главы 11
items внутри функции указывает на ТОТ ЖЕ объект-список, что и skills снаружи. .append(...) мутирует этот общий объект — поэтому изменение видно через оба имени. Это ровно тот же принцип aliasing, что мы разбирали в §11.9, только теперь одно из «двух имён» — параметр функции.

Rebinding vs mutation — сравниваем напрямую

rebinding_vs_mutation.py
def replace(items):
    items = ["new"]      # rebinding: items теперь указывает на ДРУГОЙ список

def modify(items):
    items.append("new")  # mutation: меняется ТОТ ЖЕ список
replace(items)modify(items)
Что происходитпереприсваивание локального имени itemsизменение объекта, на который items указывает
Видно снаружи после вызова?нет — снаружи всё как былода — тот же объект изменился
Главное практическое правило
Присваивание параметру (items = ...) отвязывает локальное имя от аргумента — снаружи ничего не меняется. Вызов мутирующего метода (.append(), .sort(), [i] = ...) меняет сам объект — и это видно снаружи, если объект изменяемый.
Практика: rebinding vs mutation
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки
Открыть практику →