2015-10-31 2 views
3

Я путаюсь с пропуском и передачей по значению в Python. В следующем коде, когда listB = listA, listB должен быть назначен указатель (ссылка) на список в переменной ListA. Любые изменения в listB должны быть отражены на listA. Однако это не так в моем тесте. Я что-то не так с кодом? Я бегу на Python 3.4.3Переменная списка Python не проходит по ссылке?

>>> listA = [1,2,3] 
>>> listB = listA 
>>> listA = [4,5,6] 
>>> print(listA, listB) 
[4, 5, 6] [1, 2, 3] 
>>> listB[0] ='new' 
>>> print(listA, listB) 
[4, 5, 6] ['new', 2, 3] 
+2

вы переустанавливаете 'listA', поэтому он больше не указывает на то же значение, что и' listB' – njzk2

+0

. Есть хорошие статьи о модели исполнения Python. https://www.jeffknupp.com/blog/2013/02/14/drastically-improve-your-python-understanding-pythons-execution-model/ –

ответ

2

Когда вы listA = [4,5,6], ссылка на listA (который был назначен listB) больше не указывает на listA, так как вы полностью заменили listA с новым списком.

Если вы удалите эту строку, вы обнаружите, что она работает должным образом.

2

Вы переназначаете listA в целом, поэтому нет никакой связи между ним и listB.

Например:

listA = [2,2,3] 

listB = listA 

id(listA) 
Out[6]: 90404936 

id(listB) 
Out[7]: 90404936 

listA[0]=2 

id(listA) 
Out[9]: 90404936 

listB 
Out[10]: [2, 2, 3] 

Но тогда, когда вы переназначить listA вы теряете id:

listA = [3,3,3] 

id(listA) 
Out[12]: 92762056 

Но listB остается на том же ID:

id(listB) 
Out[13]: 90404936 
1

Вы говорите:

Я путаюсь с пропуском и передачей по значению в python.

На самом деле Python не использует либо вызов по значению или вызова по ссылке: она использует call-by-object-sharing. Это в основном похоже на call-by-value, за исключением того, что рассматриваемая «ценность» на самом деле является ссылкой на объект, который содержит фактическое значение.

По сути, способ думать о переменных в Python состоит в том, что они фактически являются names that can refer to other objects, а не самими значениями.

0

Для Python подумайте о пространстве имен как реализованном таблицей с двумя столбцами, в которой перечислены имена и адреса. Также обратите внимание, что оператор присваивания = заставляет оценить правую сторону, представленную в памяти, если она еще не представлена, и , затем вызывает привязку переменной в левой части присваивания в таблице символов к адресу представление. Работа по вашему коду по одной строке за один раз:

listA = [2, 3, 4] 

вызывает 2, 3 и 4, которые должны быть представлены в памяти на определенных адресах. Затем скобки заставляют объект списка быть представленным в памяти, с адресом для класса, int для его длины и массивом адресов для его элементов. Наконец, имя listA помещается в таблицу пространства имен и привязывается к адресу для этого объекта списка.

listB = listA 

Вторая запись listB выполнена в таблице пространства имен и связан с тем же адресом для списка.

listA = [4, 5, 6] 

создает представления трех целых чисел и список в памяти и изменяет адрес, на который ссылается lišta в таблице имен, связывая его с новым списком.

listB[0] = 'new' 

вызывает строку «новая», чтобы быть представленной в памяти, а затем изменяет объект списка привязан к listB таким образом, что первый элемент этого списка теперь ссылается на адрес строки.

Если listA не был переназначен на новый объект, он будет по-прежнему указывают на тот же список, и вы увидите то же самое изменение в первом элементе списка, является ли с помощью маркера listA или listB.

Смежные вопросы