Есть ли разница между "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 в разных контекстах. Есть несколько вещей, которые представляют ложь в тестах логических значений, например, пустые контейнеры, логические значения. Никто также не оценивает ложь в этой ситуации, но другие вещи тоже.
Причина 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:".
Еще несколько деталей:
is
пункт на самом деле проверяет, если дваobject
S находятся в той же ячейке памяти или нет. то есть они оба указывают на одну и ту же ячейку памяти и имеют одинаковыеid
,Как следствие 1,
is
обеспечивает, представлены ли два лексическиobject
имеют идентичные атрибуты (атрибуты атрибутов...) или нетРеализация примитивных типов, таких как
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