Возиться с алиасингом - PullRequest
       5

Возиться с алиасингом

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

У меня есть следующий код, который работает как положено:

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

>>> b is a
True

если я немного его поменяю, он все равно работает:

a = [1, 2, 3, 4]
b = a[2] * 2

>>> b is a[2] * 2
True

Теперь проблема:

a = [1, 2, 3, 4]
b = a * 2

>>> b is a * 2
False    

Может кто-нибудь объяснить мне, почему это возвращает False, в то время как b is a[2] * 2 возвращает True?

Ответы [ 3 ]

4 голосов
/ 10 марта 2011

Когда a является списком, a * 2 создает новый экземпляр списка. Если вы вызываете a * 2 дважды, вы создаете два новых экземпляра списка - поэтому b is a * 2 дает False.

Причиной получения True для b is a[2] * 2 является оптимизация CPython, которая кэширует маленькие целые числа. Поскольку целые числа являются неизменяемыми в Python, фактически не имеет значения, получаете ли вы новый экземпляр или кэшированный, а для небольших целых чисел Python возвращает кэшированную версию, если вы снова нажмете то же самое целое число. Также попробуйте

>>> a = [1, 2, 300, 4]
>>> b = a[2] * 2
>>> b is a[2] * 2
False
2 голосов
/ 10 марта 2011

Идентичные списки не эквивалентны при сравнении is, если они не ссылаются на один и тот же список. То, что списки имеют одинаковые значения, не означает, что они ссылаются на один и тот же список в памяти.

Например,

>>> a = [1,2,3]
>>> id(a) # memory location list a references
161267628
>>> b = [1,2,3]
>>> id(b) # memory location list b references, a different memory location than list a
161276396
>>> a == b 
True
>>> a is b
False
>>> c = a # by this method of assignment; c points to the same point that a does;
# hence changes to a and changes to c, will change both.
>>> id(c) # memory location that c references; this is the same as where a points.
161267628
>>> a is c
True
>>> c.append(4)
>>> print a
[1, 2, 3, 4]
>>> print b
[1, 2, 3]
>>> print c
[1, 2, 3, 4]
>>> d = a[:] # this just copies the values in a to d.  
>>> id(d)
161277036

Это имеет смысл, что они указывают на разные области памяти, потому что, если вы хотите сказать, измените первый список (например, добавьте 4 к концу a) без изменения b, что было бы невозможно, если бы a и b указывают на одно и то же место в памяти.

0 голосов
/ 10 марта 2011

a * 2 создает новый список, в то время как целое число идентифицирует себя.

>>> type(a[2] * 2)
<type 'int'>
>>> type(a * 2)
<type 'list'>
...