Есть ли разница между "foo is None" и "foo == None"?

Есть ли разница между:

if foo is None: pass

а также

if foo == None: pass

Соглашение, которое я видел в большей части кода Python (и кода, который я сам пишу), является первым, но недавно я наткнулся на код, который использует последний. Ни один из них не является экземпляром (и единственным экземпляром, IIRC) NoneType, так что это не должно иметь значения, верно? Существуют ли обстоятельства, при которых это может произойти?

11 ответов

Решение

is всегда возвращается True если он сравнивает тот же экземпляр объекта

В то время как == в конечном итоге определяется __eq__() метод

т.е.


>>> class Foo(object):
       def __eq__(self, other):
           return True

>>> f = Foo()
>>> f == None
True
>>> f is None
False

Вы можете прочитать этот объект идентичности и эквивалентности.

Оператор "is" используется для идентификации объекта, он проверяет, ссылаются ли объекты на один и тот же экземпляр (тот же адрес в памяти).

И выражение "==" относится к равенству (то же значение).

Слово предостережения:

if foo:
  # do something

Это не то же самое, что:

if x is not None:
  # do something

Первый является тестом логического значения и может принимать значение false в разных контекстах. Есть несколько вещей, которые представляют ложь в тестах логических значений, например, пустые контейнеры, логические значения. Никто также не оценивает ложь в этой ситуации, но другие вещи тоже.

(ob1 is ob2) равно (id(ob1) == id(ob2))

Причина foo is None предпочтительным способом является то, что вы можете обрабатывать объект, который определяет свой собственный __eq__и это определяет объект равным None. Поэтому всегда используйте foo is None если вам нужно увидеть, если это на самом деле None,

Нет никакой разницы, потому что объекты, которые идентичны, конечно, будут равны. Однако в PEP 8 четко указано, что вы должны использовать is:

Сравнения с синглетами, такими как None, всегда должны выполняться с операторами is или not, а не с операторами равенства.

is тесты на идентичность, а не равенство. Для вашего заявления foo is none, Python просто сравнивает адрес памяти объектов. Это означает, что вы задаете вопрос "У меня есть два имени для одного и того же объекта?"

== с другой стороны, тесты на равенство, как это определено __eq__() метод. Это не заботится о личности.

In [102]: x, y, z = 2, 2, 2.0

In [103]: id(x), id(y), id(z)
Out[103]: (38641984, 38641984, 48420880)

In [104]: x is y
Out[104]: True

In [105]: x == y
Out[105]: True

In [106]: x is z
Out[106]: False

In [107]: x == z
Out[107]: True

None является одноэлементным оператором. Так None is None всегда верно.

In [101]: None is None
Out[101]: True

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

list1 = [1, 2, 3]
list2 = [1, 2, 3]
if list1==list2: print "Equal"
if list1 is list2: print "Same"

Это напечатало бы "Равно", так как списки имеют операцию сравнения, которая не является возвращением идентичности по умолчанию.

@ Джейсон:

Я рекомендую использовать что-то более похожее на

if foo:
    #foo isn't None
else:
    #foo is None

Мне не нравится использовать "if foo:", если foo действительно не представляет логическое значение (то есть 0 или 1). Если foo - это строка, объект или что-то еще, "if foo:" может работать, но для меня это выглядит как ленивый ярлык. Если вы проверяете, является ли x значением None, скажите "если x равен None:".

Еще несколько деталей:

  1. is пункт на самом деле проверяет, если два objectS находятся в той же ячейке памяти или нет. то есть они оба указывают на одну и ту же ячейку памяти и имеют одинаковые id,

  2. Как следствие 1, is обеспечивает, представлены ли два лексически objectимеют идентичные атрибуты (атрибуты атрибутов...) или нет

  3. Реализация примитивных типов, таких как bool, int, string(за некоторым исключением), NoneType одно и то же значение всегда будет находиться в одной и той же ячейке памяти.

Например

>>> int(1) is int(1)
True
>>> str("abcd") is str("abcd")
True
>>> bool(1) is bool(2)
True
>>> bool(0) is bool(0)
True
>>> bool(0)
False
>>> bool(1)
True

И с тех пор NoneType может иметь только один экземпляр в таблице "поиска" Python, поэтому первая и вторая являются скорее стилем программирования разработчика, который написал код (возможно, для согласованности), а не имеют какой-либо тонкой логической причины выбрать одну над другим.

Заключение Джона Мачина о том, что None является единственным выводом, основанным на этом коде.

>>> x = None
>>> y = None
>>> x == y
True
>>> x is y
True
>>> 

поскольку None это одиночка, x == None а также x is None будет иметь тот же результат. Однако, по моему эстетическому мнению, x == None лучший.

a is b # returns true if they a and b are true alias
a == b # returns true if they are true alias or they have values that are deemed equivalence 


a = [1,3,4]
b = a[:] #creating copy of list
a is b # if gives false
False
a == b # gives true
True
Другие вопросы по тегам