Кроме тривиальных типов данных, идентификаторы неизменяемых объектов python одинаковы? - PullRequest
1 голос
/ 20 апреля 2020

Для неизменяемых типов данных Python не гарантирует, что две конструкции приведут к двум разным объектам; таким образом, 1+1 is 2 может возвращать или не возвращать True. Конечно, изменяемые типы do приводят к отдельным объектам: [] is [] всегда будет возвращать False.

From https://docs.python.org/3/reference/datamodel.html#objects -values-and -типы :

Типы влияют практически на все аспекты поведения объекта. Даже важность идентичности объекта зависит в некотором смысле: для неизменяемых типов операции, которые вычисляют новые значения, могут фактически возвращать ссылку на любой существующий объект с тем же типом и значением, в то время как для изменяемых объектов это недопустимо. Например, после а = 1; b = 1, a и b могут или не могут ссылаться на один и тот же объект со значением один , в зависимости от реализации, но после c = []; d = [], c и d гарантированно ссылаются на два разных, уникальных, недавно созданных пустых списка. (Обратите внимание, что c = d = [] назначает один и тот же объект обоим c и d.)

>>> "abc" is "abc"
True
>>> [] is []
False
>>> 1 + 1 is 2
True

Теперь, кроме тривиальных типов int, float , bool, string, я ожидал бы, что tuple и frozenset будут демонстрировать одинаковое поведение.

Но я не нахожу случаев, когда они это делают:

>>> {1, 2} is {1, 2}
False
>>> (1, ) is (1, )
False

Есть ли реализации, которые дают одинаковый идентификатор для отдельных неизменяемых объектов?

1 Ответ

3 голосов
/ 20 апреля 2020

Все равенство is для этих объектов является результатом уловок интерпретатора (которые не являются частью языка spe c AFAIK, но имеют последствия CPython)

Например ( с int).

Текущая реализация хранит массив целочисленных объектов для всех целых чисел от -5 до 256, когда вы создаете int в этом диапазоне, вы на самом деле просто вернуть ссылку на существующий объект.

Таким образом, можно изменить значение 1. Я подозреваю, что поведение Python в этом случае не определено. : -)

А для строк python делает interning. bool является подклассом int (issubclass(bool, int)), который объясняет общие id для bool с. AFAIK, числа с плавающей запятой (кроме литералов в 3.8) никогда не возвращают True для is равенства.


В python3 .8, (1,) is (1,) это на самом деле True из-за к изменениям в оценке литералов.

>>> (1,) is (1,)
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True

Вместе с предупреждением об использовании is для литералов. Тем не менее, присвоение переменных и выполнение сравнения является ложным (как и ожидалось).

Обратите внимание, что tuple() is tuple() и frozenset() is frozenset() оба возвращают True. Однако их изменяемые аналоги (list и set) не имеют этого свойства.

...