Надежен ли оператор is Python для проверки ссылочного равенства изменяемых объектов? - PullRequest
3 голосов
/ 01 августа 2020

Я знаю, что оператор is в Python имеет неожиданное поведение для неизменяемых объектов, таких как целые числа и строки. См. Оператор "is" неожиданно ведет себя с целыми числами

>>> a = 0
>>> b = 0
>>> a is b
True        # Unexpected, we assigned b independently from a

Когда дело доходит до изменяемых объектов , гарантируем ли мы, что ожидаются две переменные (как написано в коде ) для ссылки на два разных объекта (с равным значением), не будет внутренне привязан к одному и тому же объекту? (Пока мы не изменим одну из двух переменных, тогда, конечно, ссылки будут отличаться.)

>>> a = [0]
>>> b = [0]
>>> a is b
# Is False guaranteed ?

Другими словами, если где-то x is y возвращает True (x и y являются изменяемыми объектами), гарантируем ли мы, что изменение x приведет к изменению и y?

1 Ответ

1 голос
/ 01 августа 2020

Пока вы думаете, что какое-то «такое» поведение является «неожиданным», ваша ментальная модель не соответствует действительности; -)

Ваш вопрос: действительно о том, когда 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-объектов).

...