Параметры в функции / методе передаются по значению или по ссылке?

1

В области Python представлены параметры в функции/методе, переданные по значению или ссылке?

Я уже провел некоторое исследование, и есть хороший ресурс: Целые числа в Python передаются по значению или ссылке?

Эта подробная информация может быть действительно хорошей ссылкой, но в основном о целых. Как ti для параметра для функции/метода

Я сделал несколько тестов/трейлов в командной строке:

his_list = [1, 2, 3]
her_list = [4, 5, 6]
def change_list1(mylist):
    mylist.append(100)
    return mylist

def change_list2(mylist):
    mylist = her_list
    return mylist

test_list1 = change_list1(his_list)
test_list2 = change_list2(his_list)
print('test_list1: {}'.format(test_list1))
print('test_list2: {}'.format(test_list2))
print('his_list: {}'.format(his_list))

test_string = change_string(his_string)
print('test_string: {}'.format(test_string))
print('his_string: {}'.format(his_string))

Результат:

test_list1: [1, 2, 3, 100]
test_list2: [4, 5, 6]
his_list: [1, 2, 3, 100]
test_string: abcdef
his_string: abc

Если параметр передается по ссылке, почему результат для change_list2 кажется переданным по значению? Кроме того, когда я поместил свой код в IDE, параметр в change_list2 изменился на серый (подразумевается, что его значение не используется)?

  • 0
    можете ли вы напечатать его список в конце
  • 0
    только что добавил результат печати для his_list
Показать ещё 2 комментария
Теги:

2 ответа

2
Лучший ответ

Python использует механизм, который известен как "Call-by-Object", иногда также называемый "Call by Object Reference" или "Call by Sharing".

Если вы передаете неизменяемые аргументы, такие как целые числа, строки или кортежи для функции, то передача действует как вызов по значению. Ссылка на объект передается параметрам функции. Они не могут быть изменены внутри функции, потому что они не могут быть изменены вообще, т.е. они неизменяемы. Это отличается, если мы передаем изменяемые аргументы. Они также передаются по объектной ссылке, но они могут быть изменены на месте в функции. Если мы передаем список функции, мы должны рассмотреть два случая: Элементы списка можно изменить на месте, т.е. Список будет изменен даже в области вызывающего. Если для имени назначен новый список, старый список не будет затронут, т.е. Список в области вызывающего абонента останется нетронутым.

ссылка: https://www.python-course.eu/passing_arguments.php

2

Python проходит по объекту. В change_list1 вы передаете изменяемый объект и мутируете его. Это тот же объект (список), просто измененный (содержимое изменено). mylist - это локальный параметр, который ссылается на объект. Функция возвращает исходный объект. Вы обнаружите, что his_list изменен, потому что он относится к одному и тому же объекту.

В change_list2 вы также передаете изменяемый объект, но вместо его изменения вы назначаете новый объект локальному параметру. Исходный объект не изменяется. Функция возвращает новый объект.

Полезно рассматривать переменные в Python как просто имена объектов. Когда вы передаете параметры функции, имена параметров в функции являются просто новыми именами для исходных объектов, переданных в функцию.

Это можно увидеть, напечатав идентификаторы имен объектов, переданных в функцию, и идентификаторы имен объектов параметров:

a = [1,2,3] # mutable object (content can be altered)
b = 1       # immutable object (content can't be altered).

print(f'id(a) = {id(a)}, id(b) = {id(b)}')

def func(c,d):
    print('INSIDE func')
    print(f'id(c) = {id(c)}, id(d) = {id(d)}')
    c.append(4)  # mutable object can be altered.
    d = 4        # local name 'd' assigned a new object.
    print('AFTER altering c & d')
    print(f'id(c) = {id(c)}, id(d) = {id(d)}')
    return c,d

e,f = func(a,b)

print('AFTER func called')
print(f'id(a) = {id(a)}, id(b) = {id(b)}')
print(f'id(e) = {id(e)}, id(f) = {id(f)}')

print(f'a = {a}, b = {b}')
print(f'e = {e}, f = {f}')

Выход:

id(a) = 2290226434440, id(b) = 1400925216
INSIDE func
id(c) = 2290226434440, id(d) = 1400925216
AFTER altering c & d
id(c) = 2290226434440, id(d) = 1400925312
AFTER func called
id(a) = 2290226434440, id(b) = 1400925216
id(e) = 2290226434440, id(f) = 1400925312
a = [1, 2, 3, 4], b = 1
e = [1, 2, 3, 4], f = 4

Обратите внимание, что идентификаторы a и b совпадают с именами параметров c и d. Имена относятся к тем же объектам.

c объект мутируется. a относится к одному и тому же объекту, поэтому будет отображаться одно и то же изменение.

d объект неизменен. Не существует таких методов, как .append для изменения содержимого объекта. d можно переназначить. Он переназначается и показывает новый идентификатор. b объект не изменяется.

После вызова функции e становится новым именем для объекта c (также называемого a). Имя c больше не существует. Это было имя локальной функции. f становится новым именем для объекта d (целое число 4) и d больше не существует. b не изменяется и ссылается на исходное целое число 1.

a и e относятся к исходному, но мутированному объекту. b и f относятся к разным неизменяемым объектам.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню