Как правило, someobj is None предпочтительнее someobj == None,
Аарон Маенпаа
как насчет псевдокода, если X не None? Или X != None?
Чарли Паркер
Ответы:
188
В первом тесте Python пытается преобразовать объект в boolзначение, если оно еще не установлено. Грубо говоря, мы спрашиваем объект: осмыслен он или нет? Это делается по следующему алгоритму:
Если у объекта есть __nonzero__специальный метод (как и встроенные числовые функции intи float), он вызывает этот метод. Он должен либо возвращать boolзначение, которое затем используется напрямую, либо intзначение, которое считается Falseравным нулю.
В противном случае, если объект имеет __len__специальный метод (как контейнер Модульные, list, dict, set, tuple, ...), он вызывает этот метод, считая контейнер , Falseесли он пуст (длина равна нуль).
В противном случае объект рассматривается, Trueесли он не рассматривается Noneв этом случае False.
Во втором тесте объект сравнивается на равенство None. Здесь мы спрашиваем объект: «Вы равны этому другому значению?» Это делается по следующему алгоритму:
Если у объекта есть __eq__метод, он вызывается, а затем возвращаемое значение преобразуется в boolзначение и используется для определения результата if.
В противном случае, если у объекта есть __cmp__метод, он вызывается. Эта функция должна возвращать intуказание порядка двух объектов ( -1если self < other, 0если self == other, +1если self > other).
В противном случае объект сравнивается на идентичность (т. Е. Они ссылаются на один и тот же объект, что может быть проверено isоператором).
С помощью isоператора возможен еще один тест . Мы бы спросили объект: «Вы этот конкретный объект?»
Как правило, я бы рекомендовал использовать первый тест с нечисловыми значениями, использовать тест на равенство, когда вы хотите сравнить объекты одного и того же характера (две строки, два числа, ...) и проверять идентичность только тогда, когда с использованием контрольных значений (то Noneесть не инициализировано для поля члена, например, или при использовании методов getattrили __getitem__).
Хотя это технически правильно, это не объясняет, что кортежи, списки, словари, строки, юникоды, целые числа, числа с плавающей запятой и т. Д. Имеют ненулевое значение . Гораздо чаще полагаться на истинностное значение встроенного типа, чем на настраиваемый ненулевой метод.
ddaa
50
На самом деле это плохая практика. Когда-то считалось нормальным небрежно относиться к None и False как к одинаковому. Однако, начиная с Python 2.2, это не лучшая политика.
Во-первых, когда вы выполняете какой- if xлибо if not xтест, Python должен неявно преобразовать xв логическое значение. Правила boolфункции описывают множество вещей, которые являются ложными; все остальное верно. Если значение x изначально не было логическим, это неявное преобразование на самом деле не самый ясный способ сказать что-то.
До Python 2.2 не было функции bool, поэтому она была еще менее понятной.
Во-вторых, вам не следует тестировать с помощью == None. Вам следует использовать is Noneи is not None.
-Comparisons to singletons like None should always be done with'is'or'is not', never the equality operators.Also, beware of writing "if x" when you really mean "if x is not None"-- e.g. when testing whether a variable or argument that defaults to
None was set to some other value.The other value might have a type
(such as a container) that could be false in a boolean context!
Сколько там синглтонов? Пять: None, True, False, NotImplementedи Ellipsis. Поскольку вы действительно вряд ли будете использовать NotImplementedили Ellipsis, и вы никогда не скажете if x is True(потому что if xэто намного яснее), вы всегда будете тестировать None.
Вторая форма - это категорически неплохая практика. PEP 8 рекомендует использовать if x дважды . Сначала для последовательностей (вместо использования len), а затем для True и False (вместо использования is). Практически весь код Python, который я видел, использует if x, а if not x.
Антти Расинен
35
Потому что Noneэто не единственное, что считается ложным.
ifnotFalse:print"False is false."ifnot0:print"0 is false."ifnot[]:print"An empty list is false."ifnot():print"An empty tuple is false."ifnot{}:print"An empty dict is false."ifnot"":print"An empty string is false."
False, 0, (), [], {}И ""все отличаются от None, так что ваши два фрагменты кода не эквивалентны.
Кроме того, учтите следующее:
>>>False==0True>>>False==()False
if object:это не проверка на равенство. 0, (), [], None, {}И т.д. являются все отличаются друг от друга, но все они оценивают Ложь.
Что касается вашего последнего вопроса, они равнозначны.
Sylvain Defresne
И оба неверны, потому что "" ложно. Второй должен читать '("",) или ("s",)'. В любом случае, в современных версиях python есть правильный тернарный оператор. Этот способный к ошибкам взлом должен быть исключен.
__nonzero__ метод спам вызывается. Из руководства Python:
__nonzero__ ( self ) Вызывается для реализации проверки истинности и встроенной операции bool (); должен возвращать False или True или их целочисленные эквиваленты 0 или 1. Когда этот метод не определен, вызывается __len __ (), если он определен (см. ниже). Если класс не определяет ни __len __ (), ни __nonzero __ (), все его экземпляры считаются истинными.
Чтобы быть абсолютно правильным, второй проверяет -equality- со значением None ... "someobj is None" проверяет идентичность.
Мэтью Тревор,
0
Во-первых, первый пример короче и выглядит лучше. В соответствии с другими сообщениями то, что вы выберете, также зависит от того, что вы действительно хотите делать со сравнением.
Лично я выбрал последовательный подход для разных языков: я делаю if (var)(или эквивалент), только если var объявлен как логический (или определен как таковой, в C у нас нет определенного типа). Я даже ставлю перед этими переменными префикс b(так было бы на bVarсамом деле), чтобы быть уверенным, что случайно не использую здесь другой тип.
Мне не нравится неявное приведение к логическому типу, тем более, когда существует множество сложных правил.
Конечно, люди не согласятся. Некоторые идут дальше, я вижу if (bVar == true)в Java-коде в своей работе (слишком избыточный на мой вкус!), Другим нравится слишком компактный синтаксис, идущий while (line = getNextLine())(слишком неоднозначный для меня).
X != None
?Ответы:
В первом тесте Python пытается преобразовать объект в
bool
значение, если оно еще не установлено. Грубо говоря, мы спрашиваем объект: осмыслен он или нет? Это делается по следующему алгоритму:Если у объекта есть
__nonzero__
специальный метод (как и встроенные числовые функцииint
иfloat
), он вызывает этот метод. Он должен либо возвращатьbool
значение, которое затем используется напрямую, либоint
значение, которое считаетсяFalse
равным нулю.В противном случае, если объект имеет
__len__
специальный метод (как контейнер Модульные,list
,dict
,set
,tuple
, ...), он вызывает этот метод, считая контейнер ,False
если он пуст (длина равна нуль).В противном случае объект рассматривается,
True
если он не рассматриваетсяNone
в этом случаеFalse
.Во втором тесте объект сравнивается на равенство
None
. Здесь мы спрашиваем объект: «Вы равны этому другому значению?» Это делается по следующему алгоритму:Если у объекта есть
__eq__
метод, он вызывается, а затем возвращаемое значение преобразуется вbool
значение и используется для определения результатаif
.В противном случае, если у объекта есть
__cmp__
метод, он вызывается. Эта функция должна возвращатьint
указание порядка двух объектов (-1
еслиself < other
,0
еслиself == other
,+1
еслиself > other
).В противном случае объект сравнивается на идентичность (т. Е. Они ссылаются на один и тот же объект, что может быть проверено
is
оператором).С помощью
is
оператора возможен еще один тест . Мы бы спросили объект: «Вы этот конкретный объект?»Как правило, я бы рекомендовал использовать первый тест с нечисловыми значениями, использовать тест на равенство, когда вы хотите сравнить объекты одного и того же характера (две строки, два числа, ...) и проверять идентичность только тогда, когда с использованием контрольных значений (то
None
есть не инициализировано для поля члена, например, или при использовании методовgetattr
или__getitem__
).Подводя итог, мы имеем:
источник
На самом деле это плохая практика. Когда-то считалось нормальным небрежно относиться к None и False как к одинаковому. Однако, начиная с Python 2.2, это не лучшая политика.
Во-первых, когда вы выполняете какой-
if x
либоif not x
тест, Python должен неявно преобразоватьx
в логическое значение. Правилаbool
функции описывают множество вещей, которые являются ложными; все остальное верно. Если значение x изначально не было логическим, это неявное преобразование на самом деле не самый ясный способ сказать что-то.До Python 2.2 не было функции bool, поэтому она была еще менее понятной.
Во-вторых, вам не следует тестировать с помощью
== None
. Вам следует использоватьis None
иis not None
.См. PEP 8, Руководство по стилю кода Python .
Сколько там синглтонов? Пять:
None
,True
,False
,NotImplemented
иEllipsis
. Поскольку вы действительно вряд ли будете использоватьNotImplemented
илиEllipsis
, и вы никогда не скажетеif x is True
(потому чтоif x
это намного яснее), вы всегда будете тестироватьNone
.источник
Потому что
None
это не единственное, что считается ложным.False
,0
,()
,[]
,{}
И""
все отличаются отNone
, так что ваши два фрагменты кода не эквивалентны.Кроме того, учтите следующее:
if object:
это не проверка на равенство.0
,()
,[]
,None
,{}
И т.д. являются все отличаются друг от друга, но все они оценивают Ложь.Это «волшебство» таких выражений, как:
что является сокращением для:
хотя вам действительно стоит написать:
источник
PEP 8 - Руководство по стилю для кода Python рекомендует использовать есть или нет, если вы тестируете на None-ness
С другой стороны, если вы тестируете больше, чем None-ness, вам следует использовать логический оператор.
источник
Если вы спросите
__nonzero__ метод спам вызывается. Из руководства Python:
Если вы спросите
__eq__ метод спам вызывается с аргументом None .
Для получения дополнительной информации о возможностях настройки см. Документацию Python по адресу https://docs.python.org/reference/datamodel.html#basic-customization
источник
Эти два сравнения служат разным целям. Первый проверяет логическое значение чего-либо, второй проверяет идентичность со значением None.
источник
Во-первых, первый пример короче и выглядит лучше. В соответствии с другими сообщениями то, что вы выберете, также зависит от того, что вы действительно хотите делать со сравнением.
источник
Ответ - «это зависит от обстоятельств».
Я использую первый пример, если считаю, что 0, "", [] и False (список не исчерпывающий) эквивалентны None в этом контексте.
источник
Лично я выбрал последовательный подход для разных языков: я делаю
if (var)
(или эквивалент), только если var объявлен как логический (или определен как таковой, в C у нас нет определенного типа). Я даже ставлю перед этими переменными префиксb
(так было бы наbVar
самом деле), чтобы быть уверенным, что случайно не использую здесь другой тип.Мне не нравится неявное приведение к логическому типу, тем более, когда существует множество сложных правил.
Конечно, люди не согласятся. Некоторые идут дальше, я вижу
if (bVar == true)
в Java-коде в своей работе (слишком избыточный на мой вкус!), Другим нравится слишком компактный синтаксис, идущийwhile (line = getNextLine())
(слишком неоднозначный для меня).источник