Идентичность против равенства для None в Python
Различные руководства Python говорят использовать x is None
вместо x == None
. Почему это? Равенство используется для сравнения значений, поэтому естественно спросить, имеет ли x
значение None
, обозначенное ==
, а не is
. Может ли кто-нибудь объяснить, почему is
является предпочтительной формой и показывает пример, где два не дают тот же ответ?
Спасибо.
Ответы
Ответ 1
Причина, по которой люди используют is
, состоит в том, что нет преимущества при использовании ==
. Можно записывать объекты, которые сравниваются с None
, но это необычно.
class A(object):
def __eq__(self, other):
return True
print A() == None
Вывод:
True
Оператор is
также быстрее, но я не считаю этот факт важным.
Ответ 2
Идентификатор ключевого слова is
. Это не оператор сравнения, например ==
. Использование is
делает больше, чем проверка того, имеют ли два аргумента одно и то же значение и/или одну и ту же внутреннюю структуру: именно он проверяет, действительно ли эти два относятся к одному и тому же объекту в памяти. Есть много последствий для этого, один из которых заключается в том, что is
не может быть перегружен, а другое - поведение, которое отличается от изменяемых и неизменяемых типов. Например, рассмотрим следующее:
>>> l1 = range(5)
>>> l2 = range(5)
>>> l1 == l2
True
>>> l1 is l2
False
>>> l3 = l1
>>> l1 is l3
True
>>> s1 = "abcde"
>>> s2 = "abcde"
>>> s1 == s2
True
>>> s1 is s2
True
Здесь, поскольку списки изменяемы, они не могут делить местоположение в памяти, и, следовательно, is
и ==
дают несоответствующие результаты. С другой стороны, строки неизменяемы, и поэтому их память может быть объединена в некоторых случаях. В принципе, is
можно надежно использовать только для простых, неизменяемых типов или в случаях, когда несколько имен указывают на один и тот же объект в памяти (например, использование l3
в приведенном выше примере), а его использование указывает на желание испытать идентичность, а не ценность. Я ожидал бы, что is
будет немного быстрее, чем ==
, потому что он не выполняет поиск метода, но я могу ошибаться. Конечно, для сложных объектов контейнера, таких как списки или dicts, is
должен быть намного быстрее, чем ==
(O (1) против O (n), предположительно). Тем не менее, проблема скорости в основном спорная, поскольку эти два не следует рассматривать как взаимозаменяемые.
Ответ 3
PEP 8 говорит:
"Сравнение с синглонами типа" Нет "всегда должно выполняться с помощью" есть "или" нет ", а не операторов равенства". Вот довольно хорошее объяснение, почему:
http://jaredgrubb.blogspot.com/2009/04/python-is-none-vs-none.html