2014-01-13 2 views

ответ

9

Ваш первый фрагмент создает два уникальных объектов списка, которые не являются одинаковыми. Следовательно a is b возвращает ложь, потому что a и b указывают на отдельные объекты:

 
      +------+ 
a ------> | list | 
      +------+ 

      +------+ 
b ------> | list | 
      +------+ 

Ваш второй фрагмент кода создает единый список объектов, и указывает как c и d в том, что объекты, следовательно, c is d возвращающие:

 
      +------+ 
c ------> | list | <------ d 
      +------+ 

Обратите внимание на следующее, из http://docs.python.org/3/reference/datamodel.html:

Каждый объект имеет идентификатор, тип и значение. Идентификатор объекта никогда не изменяется после его создания; вы можете думать об этом как о адресе объекта в памяти. Оператор is сравнивает идентичность двух объектов; функция id() возвращает целое число, представляющее его идентификатор.

is и == очень разные; в то время как первый сравнивает идентичность объекта, последний сравнивает значения объектов. Действительно, тесты == в ваших фрагментах вернут true.


Учитывая вышеизложенное объяснение, это может стать неожиданностью, что эта история немного отличается со строками:

>>> a = 'str' 
>>> b = 'str' 
>>> 
>>> a is b 
True 

Это связано с string interning, что происходит в CPython (т.е. это зависит от конкретной реализации). Поэтому, если один и тот же строковый литерал отображается в двух разных местах, тот же строковый объект будет использоваться для обоих (с ограничениями).

Подробнее об этом говорится в "Python string interning".

+0

+1 для ASCII Art: p – thefourtheye

+0

Итак, почему результат обоих - это '' True'', если я попытаюсь сделать это на неизменяемом объекте, таком как str '' spam'', а не в списке '' ['spam'] '' –

+1

@YousufMemon Это потому, что [строки интернированы в CPython] (http://stackoverflow.com/questions/15541404/python-string-interning). – arshajii

1

Позвольте мне добавить несколько вызовов функций к тому, что вы изначально делали. Думаю, ты его поднимешь.

>>> a = ['spam'] 
>>> b = ['spam'] 
>>> a is b 
False 
>>> id(a) 
4552359808 
>>> id(b) 
4552446176 
>>> a == b 
True 
>>> c = ['spam'] 
>>> d = c 
>>> id(c) 
4552513296 
>>> id(d) 
4552513296 
>>> c is d 
True 
>>> c == d 
True 
>>> print id.__doc__ 
id(object) -> integer 

Return the identity of an object. This is guaranteed to be unique among 
simultaneously existing objects. (Hint: it's the object's memory address.) 
4

при сравнении с is, как a is b, это то же самое, как id(a) == id(b), код xx=['spam'] создает новый список каждый раз и присваивает его xx, это id изменяется каждый раз, поэтому a is b дает ложных

2

Это не имеет никакого отношения к какому-то (неутомимому) вопросу «присваивание против ссылки».

>>> a = ['spam'] 

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

>>> b = ['spam'] 

создает еще один список с строкой «спам» в нем, и связывает его с именами «Ъ» в текущей области.

Вы создаете два списка, у вас есть два списка. Простое.

>>> c = ['spam'] 

создает еще один список с струнной «спам» в нем, и связывает его с именами «C» в текущей области.

>>> d = c 

связывает имя 'd' с тем, что 'c' привязано к этому моменту в текущей области.

Здесь вы создаете один список и связываете с ним 2 имени. Оба названия указывают на один и тот же объект.

Дело в том, что «переменные» Python не называются именами памяти, просто именами, указывающими на объекты. В данный момент один объект может быть привязан к (указанному) любым числом имен (и даже вообще не именем).

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