Почему id ({}) == id ({}) и id () == id () в CPython?

Почему CPython (не знает о других реализациях Python) имеет следующее поведение?

tuple1 = () tuple2 = () dict1 = {} dict2 = {} list1 = [] list2 = [] # makes sense, tuples are immutable assert(id(tuple1) == id(tuple2)) # also makes sense dicts are mutable assert(id(dict1) != id(dict2)) # lists are mutable too assert(id(list1) != id(list2)) assert(id(()) == id(())) # why no assertion error on this? assert(id({}) == id({})) # or this? assert(id([]) == id([])) 

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

РЕДАКТИРОВАТЬ

Чтобы еще раз подтвердить точку Гленна и Томаса:

 [1] id([]) 4330909912 [2] x = [] [3] id(x) 4330909912 [4] id([]) 4334243440 

  • «is» оператор неожиданно ведет себя с поплавками
  • Почему deque реализован как связанный список вместо кругового массива?
  • Почему str.strip () намного быстрее, чем str.strip ('')?
  • Когда обновляются файлы .pyc?
  • Что такое __signature__ и __text_signature__, используемые в Python 3.4
  • Есть ли что-то быстрее, чем dict ()?
  • Как кортеж реализован в CPython?
  • Как юникод представлен внутри Python?
  • 4 Solutions collect form web for “Почему id ({}) == id ({}) и id () == id () в CPython?”

    CPython – это сбор мусора, как только они выходят из области видимости, поэтому второй [] создается после первого сбора [] . Поэтому большую часть времени он попадает в одно и то же место памяти.

    Это показывает, что происходит очень четко (вывод, вероятно, будет отличаться в других реализациях Python):

     class A(object): def __init__(self): print "a", def __del__(self): print "b", # aabb False print A() is A() # abab True print id(A()) == id(A()) 

    Когда вы вызываете id({}) , Python создает dict и передает его функции id . Функция id принимает свой идентификатор (ячейку памяти) и отбрасывает dict. Дик разрушен. Когда вы делаете это дважды в быстрой последовательности (без каких-либо других dicts, создаваемых в среднее время), dict Python создает второй раз, когда используется тот же блок памяти, что и в первый раз. (Распределитель памяти CPython делает это гораздо более вероятным, чем кажется). Поскольку (в CPython) id использует ячейку памяти в качестве идентификатора объекта, идентификатор двух объектов одинаковый. Это, очевидно, не происходит, если вы назначаете dict переменной, а затем получаете ее id() , потому что dicts являются живыми одновременно , поэтому их id должен быть другим.

    Мутируемость напрямую не вступает в игру, но кодовые объекты кэшируют кортежи и строки. В том же объекте кода (функция или тело тела тела или тела модуля) будут повторно использоваться те же литералы (целые числа, строки и некоторые кортежи). Переменные объекты никогда не могут быть повторно использованы, они всегда создаются во время выполнения.

    Короче говоря, идентификатор объекта уникален только для времени жизни объекта . После уничтожения объекта или до его создания что-то еще может иметь один и тот же идентификатор.

    он не работает одинаково в Jython …

     >>> id({}) 1 >>> id([]) 2 

    Может ли быть проведена оптимизация, когда обычно используемые (т.е. пустые) контейнеры «интернированы», чтобы сэкономить на расходах на размещение?

    Это (в CPython) не предполагает:

     >>> def mutateid(obj): ... obj.append('x') ... print obj ... print id(obj) ... >>> mutateid([]) ['x'] 4299590472 >>> id([]) 4299590472 >>> 

    Оператор == в списках и dicts не сравнивает идентификаторы объектов, чтобы увидеть, является ли они одним и тем же объектом. Для этого используется obj1 is obj2 для obj1 is obj2 .

    Вместо этого оператор == сравнивает членов списка dict, чтобы проверить, совпадают ли они.

    Python - лучший язык программирования в мире.