Ваш первый фрагмент создает два уникальных объектов списка, которые не являются одинаковыми. Следовательно 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".
+1 для ASCII Art: p – thefourtheye
Итак, почему результат обоих - это '' True'', если я попытаюсь сделать это на неизменяемом объекте, таком как str '' spam'', а не в списке '' ['spam'] '' –
@YousufMemon Это потому, что [строки интернированы в CPython] (http://stackoverflow.com/questions/15541404/python-string-interning). – arshajii