Python - точно так же, как Java делает для чего угодно, кроме примитивных скаляров, и как C # и VB.NET делают для параметров вида по умолчанию в отличие от штучных типов и параметров out / ref - передает «по ссылке на объект» (поиск эта фраза здесь - это то, что Гвидо, архитектор и создатель Python, использует для объяснения этой концепции передачи аргументов).
Каждое имя является ссылкой на некоторый объект; передача имени (или любого другого выражения) в качестве аргумента просто создает еще одну ссылку на тот же объект (к которому тело функции может получить доступ через имя параметра). ((Нет такой вещи как «ссылка на имя»: есть имена , которые являются одним из видов ссылки на объекты, а объект - точка)).
Когда вы передаете изменяемый объект, то есть тот, у которого есть изменяющие методы (например, список), вызываемая функция может изменять объект, вызывая, прямо или косвенно, его изменяющие методы. ((Под «косвенно» я имею в виду «через операторов» - например:
somelist[len(somelist):] = [whatever]
в точности совпадает с somelist.append(whatever)
.))
Если вы хотите передать список в функцию, но не хотите, чтобы функция могла каким-либо образом изменять этот список, вы должны передать копию список вместо оригинала - как в Java, C #, VB.NET.
Будьте очень ясно о различии между повторным связыванием имени и , мутировавшего с объектом . Перепривязка имени («barename», то есть - квалифицированные имена отличаются ;-) только влияет на то, что name - NOT любой объект вообще. Например:
def f1(alist):
alist = [23]
def f2(alist):
alist[:] = [23]
Можете ли вы определить разницу между этими двумя функциями? Один из них - это повторное связывание barename alist
- без какого-либо влияния на что-либо. Другой - мутирование (изменение, изменение, ...) объекта списка, который он получил в качестве аргумента, - путем установки его содержимого в виде списка из одного элемента с int как единственным элементом. Совершенно, совершенно разные вещи !!!