Есть ли какая-то разница между “foo is None” и “foo == None”?
-
09-06-2019 - |
Вопрос
Есть ли какая-то разница между:
if foo is None: pass
и
if foo == None: pass
Соглашение, которое я видел в большинстве кодов Python (и в коде, который я сам пишу), является первым, но недавно я наткнулся на код, который использует последнее.None - это экземпляр (и единственный экземпляр, IIRC) NoneType , так что это не должно иметь значения, верно?Есть ли какие-то обстоятельства, при которых это могло бы произойти?
Решение
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 в различных контекстах.Есть ряд вещей, которые представляют false в тестах с логическими значениями, например, пустые контейнеры, логические значения.В этой ситуации None также принимает значение false, но и другие вещи тоже принимают значение false.
(ob1 is ob2)
равный (id(ob1) == id(ob2))
Причина foo is None
предпочтительный способ заключается в том, что вы можете обрабатывать объект, который определяет свой собственный __eq__
, и это определяет, что объект равен None.Итак, всегда используйте foo is None
если вам нужно убедиться, что это действительно так None
.
Здесь нет никакой разницы, потому что объекты, которые идентичны, конечно, будут равны.Однако, БОДРОСТЬ ДУХА 8 четко указано, что вы должны использовать is
:
Сравнения с синглетонами типа None всегда должны выполняться с помощью is или 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
Ни для кого не должно быть разницы между равенством (==) и идентичностью (is).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
находятся в одной и той же ячейке памяти или нет.т.е. указывают ли они оба на одну и ту же ячейку памяти и имеют ли одинаковыйid
.Как следствие 1,
is
гарантирует, будут ли эти два лексически представленыobject
они имеют идентичные атрибуты (attributes-of-attributes ...) или нетСоздание экземпляров примитивных типов, таких как
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