Когда оператор `==` не эквивалентен оператору `is`? (Python) - PullRequest
11 голосов
/ 06 сентября 2010

Я заметил, что могу использовать оператор == для сравнения всех собственных типов данных (целых, строк, логических значений, чисел с плавающей запятой и т. Д.), А также списков, кортежей, наборов и словарей, которые содержат собственные типы данных.В этих случаях оператор == проверяет, равны ли два объекта.Но в некоторых других случаях (при попытке сравнить экземпляры созданных мною классов) оператор == просто проверяет, ссылаются ли две переменные на один и тот же объект (поэтому в этих случаях оператор == эквивалентен оператору is)

Мой вопрос: когда оператор == делает больше, чем просто сравнение тождеств?

РЕДАКТИРОВАТЬ: я использую Python 3

Ответы [ 4 ]

19 голосов
/ 06 сентября 2010

В Python оператор == реализован в терминах магического метода __eq__, который по умолчанию реализует его путем сравнения идентификаторов.Однако вы можете переопределить метод, чтобы предоставить собственную концепцию равенства объектов.Обратите внимание, что если вы это сделаете, вы, как правило, также переопределите по крайней мере __ne__ (который реализует оператор !=) и __hash__, который вычисляет хеш-код для экземпляра.даже в Python очень полезно, чтобы мои реализации __eq__ соответствовали правилам, изложенным в языке Java для реализаций метода equals, а именно:

  • Это рефлексивно: для любого ненулевого ссылочного значения x, x.equals (x) должно возвращать true.
  • Это симметрично: для любых ненулевых ссылочных значений x и y, x.equals (y)должен возвращать true тогда и только тогда, когда y.equals (x) возвращает true.
  • Это транзитивно: для любых ненулевых ссылочных значений x, y и z, если x.equals (y) возвращает true иy.equals (z) возвращает true, тогда x.equals (z) должен возвращать true.
  • Это согласуется: для любых ненулевых ссылочных значений x и y несколько вызовов x.equals (y)последовательно возвращать истину или последовательно возвращать ложь при условии, что при сравнении не используется информацияns для объектов изменяется.
  • Для любого ненулевого ссылочного значения x, x.equals (null) должен возвращать false.

последний, вероятно, должен заменить null на None, но правила здесь не так просты в Python, как в Java.

18 голосов
/ 06 сентября 2010

== и is всегда концептуально различны: первые делегаты левого объекта __eq__ [1], последние всегда проверяют идентичность без какого-либо делегирования. Что вас смущает, так это то, что object.__eq__ (который наследуется по умолчанию пользовательскими классами, которые его не переопределяют, конечно!) Реализован с точки зрения идентичности (в конце концов, голый object имеет абсолютно ничего для проверки , кроме его личности, так что еще он может сделать?! -).

[1] опуская для простоты унаследованную концепцию метода __cmp__, которая является лишь незначительным осложнением и не меняет ничего важного в сущности абзаца; -).

7 голосов
/ 06 сентября 2010

== делает больше, чем сравнение идентичности, когда задействованы целые числа. Он не просто проверяет, что два целых являются одним и тем же объектом; это фактически гарантирует, что их значения совпадают. Рассмотрим:

>>> x=10000
>>> y=10000
>>> x==y,x is y
(True, False)
>>> del x
>>> del y
>>> x=10000
>>> y=x
>>> x==y,x is y
(True, True)

«Стандартная» реализация Python делает некоторые вещи за кулисами для маленьких целых, поэтому при тестировании с небольшими значениями вы можете получить что-то другое. Сравните это с эквивалентным 10000 случаем:

>>> del y
>>> del x
>>> x=1
>>> y=1
>>> x==y,x is y
(True, True)
4 голосов
/ 06 сентября 2010

Что, возможно, является наиболее важным моментом, так это рекомендация всегда использовать:

if myvalue is None:

, а не

if myvalue == None:

И никогда не использовать:

if myvalue is True:

но используйте:

if myvalue:

Этот более поздний момент не настолько уж ясен для меня, так как я думаю, что есть времена, чтобы отделить логическое значение True от других значений True, таких как "Алекс Мартелли", скажем, нет False in "Алекс Мартелли "(абсолютно нет, это даже вызывает исключение :)), но в" Алекс Мартелли "есть (как и в любой другой строке).

...