Пока вы думаете, что какое-то «такое» поведение является «неожиданным», ваша ментальная модель не соответствует действительности; -)
Ваш вопрос: действительно о том, когда Python гарантирует для создания нового объекта. А когда этого не происходит. Для изменяемых объектов да, конструктор (включая литерал), создающий изменяемый объект, всегда создает новый объект. Вот почему:
>>> a = [0]
>>> b = [0]
>>> a is b
всегда False
. Python мог бы сказать, что не определено, создает ли каждый экземпляр [0]
новый объект, но это не так: он гарантирует, что каждый экземпляр всегда создает новый объект. Поведение is
является следствием этого, а не его драйвером.
Аналогично,
>>> a = set()
>>> b = set()
>>> a is b
False
также гарантируется. Поскольку set()
возвращает изменяемый объект, он всегда гарантирует создание нового такого объекта.
Но для неизменяемых объектов он не определен . Например, результат этого не определен:
>>> a = frozenset()
>>> b = frozenset()
>>> a is b
frozenset()
- как целочисленные литералы - возвращает неизменяемый объект, и реализация зависит от того, возвращать ли новый объект или повторно использовать существующий. . В этом конкретном примере c a is b
равно True
, потому что реализация du jour происходит для повторного использования пустого Frozenset. Но, например, так получилось, что
>>> a = frozenset([3])
>>> b = frozenset([3])
>>> a is b
False
сегодня. С таким же успехом он мог бы вернуть True
завтра (хотя это маловероятно - хотя пустой Frozenset - это легко обнаруживаемый частный случай, было бы дорого гарантировать уникальность для всех Frozenset-объектов).