Классические термины by value/by reference плохо ложатся на модель Python, поэтому корректнее говорить о передаче по объектной ссылке (call by object reference или call by sharing).
Что это означает на практике
При вызове функции создаются новые имена в локальной области видимости, которые указывают на уже существующие объекты.
Если внутри функции ты изменяешь сам объект (например, список через .append()), это изменение видно снаружи.
Если внутри функции ты переназначаешь локальное имя на новый объект (obj = ...), это не влияет на то, на что ссылается имя снаружи.
Примеры с изменяемыми и неизменяемыми объектами
def add_one(x):
x += 1
n = 10
add_one(n)
print(n) # 10, не изменился
Числа — неизменяемые объекты. Операция x += 1 создаёт новый объект и перепривязывает локальное имя x на него. Снаружи переменная n продолжает ссылаться на старый объект.
def append_item(items):
items.append(42)
lst = []
append_item(lst)
print(lst) # [42], список изменился
Списки — изменяемые. append меняет объект по месту; и локальное имя items, и внешнее lst указывают на один и тот же список, поэтому изменение видно снаружи.
Как это корректно сформулировать на собеседовании
В Python в функцию передаются ссылки на объекты, а не сами объекты по значению и не «указатели», как в C. Если ты мутируешь объект внутри функции (список, словарь, свой экземпляр класса), изменения видны снаружи. Если ты просто переназначаешь локальный параметр на новый объект, это не затрагивает внешнюю переменную. Такой подход обычно описывают как call by object reference или call by sharing.