Ответ
В Python используется механизм передачи аргументов, известный как call by object reference (или call by sharing). Это означает, что в функцию передается копия ссылки на объект, а не сам объект или его полная копия.
Поведение зависит от типа данных (изменяемый или неизменяемый):
-
Неизменяемые типы (immutable):
int,str,tuple,frozenset. При попытке изменить такой объект внутри функции создается новый объект, и локальная переменная функции начинает ссылаться на него. Исходный объект вне функции остается без изменений.def change_immutable(s): # Создается новая строка, и 's' теперь ссылается на нее s = s + " world" print(f"Внутри функции: {s}") # Внутри функции: hello world my_string = "hello" change_immutable(my_string) print(f"Снаружи функции: {my_string}") # Снаружи функции: hello -
Изменяемые типы (mutable):
list,dict,set. Поскольку функция получает ссылку на тот же самый объект, изменение его внутреннего состояния (например, добавление элемента в список) будет видно и за пределами функции.def change_mutable(lst): # Объект изменяется по ссылке lst.append(4) print(f"Внутри функции: {lst}") # Внутри функции: [1, 2, 3, 4] my_list = [1, 2, 3] change_mutable(my_list) print(f"Снаружи функции: {my_list}") # Снаружи функции: [1, 2, 3, 4]
Ключевой момент: Оператор присваивания (=) внутри функции всегда создает новую локальную ссылку и никогда не изменяет переменную вне ее области видимости.
Ответ 18+ 🔞
Давай разберёмся с этой питонячьей фигней про передачу аргументов, а то народ путается, как последние идиоты. Сидишь такой, пишешь код, думаешь — ну щас я тут внутри функции всё поменяю, а снаружи будет охуенно. А потом — пиздец, ничего не работает, и ты сидишь, чешешь репу, как обезьяна с гранатой.
Вот смотри, в Python это называется call by object reference, или, по-нашему, «передача по ссылке на объект». По сути, в функцию летит не сам объект, а копия ссылки на него. Как будто ты дал другу дубликат ключа от своей квартиры, а не переехал к нему всей семьёй.
И тут вся соль — в типах данных, блядь. Они делятся на два лагеря:
-
Неизменяемые (immutable):
int,str,tuple,frozenset. Это как каменная скрижаль, высеченная в граните. Попробуй её изменить внутри функции — хуй там! Вместо этого создаётся новый объект, и твоя локальная переменная начинает тыкать пальцем уже в него. Оригинал снаружи остаётся нетронутым, как святой.def change_immutable(s): # Тут рождается новая строка, и 's' теперь смотрит на неё s = s + " world" print(f"Внутри функции: {s}") # Внутри функции: hello world my_string = "hello" change_immutable(my_string) print(f"Снаружи функции: {my_string}") # Снаружи функции: helloВидишь? Снаружи всё та же «hello». Функция порезвилась со своей копией, а твоя переменная даже не чихнула.
-
Изменяемые (mutable):
list,dict,set. А вот это уже трясина, болото! Объект один и тот же, и ссылка ведёт прямо к нему в логово. Начал внутри функции ковыряться — так он и снаружи весь изгаженный будет.def change_mutable(lst): # Объект меняется по той же самой ссылке, ёпта! lst.append(4) print(f"Внутри функции: {lst}") # Внутри функции: [1, 2, 3, 4] my_list = [1, 2, 3] change_mutable(my_list) print(f"Снаружи функции: {my_list}") # Снаружи функции: [1, 2, 3, 4]Вот тут уже овердохуища! Добавили четвёрку внутри, и она прилипла, как дерьмо к ботинку, и снаружи. Потому что список — он один, а ссылок на него — две.
Главный подвох, на котором все ебутся: оператор присваивания (=) внутри функции — это всегда создание новой локальной ссылки. Он никогда не идёт менять какую-то переменную снаружи, это не его ебаная работа. Хочешь изменить что-то снаружи — лезь прямо в кишки изменяемого объекта, если он, конечно, mutable. А иначе — в рот меня чих-пых, ничего не выйдет.