Область переменных Python (передача по ссылке или копированию?) - PullRequest
10 голосов
/ 08 марта 2011

Почему переменная L обрабатывается при вызове функции sorting(L)?На других языках копия L будет передана в sorting() как копия, чтобы любые изменения в x не изменили исходную переменную?

def sorting(x):
    A = x #Passed by reference?
    A.sort() 

def testScope(): 
    L = [5,4,3,2,1]
    sorting(L) #Passed by reference?
    return L

>>> print testScope()

>>> [1, 2, 3, 4, 5]

Ответы [ 4 ]

15 голосов
/ 08 марта 2011

Короче говоря: Python использует передачу по значению, но вещи, которые передаются по значению, являются ссылками.Реальные объекты имеют ссылки на 0 до бесконечности, указывающие на них, и для целей мутирования этого объекта не имеет значения, кто вы есть и как вы получили ссылку на объект.

Проходя по вашему примеру, шаг за шагомшаг:

  • L = [...] создает где-то в памяти объект list, локальная переменная L хранит ссылку на этот объект.
  • sorting (строго говоря,вызываемый объект, указанный как глобальное имя sorting), вызывается с копией ссылки, хранящейся в L, и сохраняет ее в локальной папке с именем x.
  • Метод sort изобъект, на который указывает ссылка, содержащаяся в x, вызывается.Он также получает ссылку на объект (в параметре self).Он каким-то образом видоизменяет этот объект ( объект , а не некоторую ссылку на объект, который является просто больше, чем адрес памяти).
  • Теперь, поскольку ссылки были скопированы, а не объектссылки указывают на, все другие ссылки, которые мы обсуждали, все еще указывают на тот же объект.Один объект, который был изменен «на месте».
  • testScope затем возвращает другую ссылку на этот объект списка.
  • print использует его для запроса строкового представления (вызывает __str__ метод) и выводит его.Поскольку это все тот же объект, конечно, он печатает отсортированный список.

Поэтому, когда вы передаете объект где-либо, вы делитесь с тем, кто его получает.Функции могут (но обычно не будут) мутировать объекты (на которые указывают ссылки), которые они передают, от вызова мутационных методов до назначения членов.Обратите внимание, что назначение члена отличается от назначения простого старого имени, что означает лишь изменение вашей локальной области видимости, а не каких-либо объектов вызывающего.Таким образом, вы не можете изменять локальные параметры вызывающего абонента (вот почему это не переход по ссылке).

Дальнейшее чтение: Обсуждение на сайте effbot.org почему это не переход по ссылкессылка, а не то, что большинство людей назвали бы передачей по значению.

9 голосов
/ 08 марта 2011

В Python есть концепция изменяемых и неизменных объектов . Объект, такой как строка или целое число, является неизменным - каждое внесенное вами изменение создает новую строку или целое число.

Списки изменчивы и ими можно манипулировать. Смотри ниже.

a = [1, 2, 3]
b = [1, 2, 3]
c = a

print a is b, a is c
# False True

print a, b, c
# [1, 2, 3] [1, 2, 3] [1, 2, 3]
a.reverse()
print a, b, c
# [3, 2, 1] [1, 2, 3] [3, 2, 1]
print a is b, a is c
# False True

Обратите внимание, как с был обратный, потому что с "есть" а. Есть много способов скопировать список в новый объект в памяти. Простой метод - нарезать: c = a[:]

1 голос
/ 08 марта 2011

В документации специально упоминается, что функция .sort() изменяет коллекцию.Если вы хотите перебрать отсортированную коллекцию, используйте sorted(L).Это обеспечивает генератор вместо простой сортировки списка.

0 голосов
/ 08 марта 2011
a = 1
b = a
a = 2
print b

Ссылки не являются отдельными объектами.

.sort() также изменяет коллекцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...