Если A vs, если A не является None:

Могу ли я использовать:

if A:

вместо

if A is not None:

Последнее кажется таким подробным. Есть ли разница?

Ответ 1

Утверждение

if A:

вызовет A.__nonzero__() (см. специальные имена методов) и используйте возвращаемое значение этой функции. Здесь резюме:

object.__nonzero__(self)

Вызывается для реализации тестирования истины и встроенной операции bool(); должен возвращать False или True, или их целые эквиваленты 0 или 1. Когда этот метод не определен, вызывается __len__(), если он определен, и объект считается истинным, если его результат отличен от нуля. Если класс не определяет ни __len__(), ни __nonzero__(), все его экземпляры считаются истинными.

С другой стороны,

if A is not None:

сравнивает только ссылку A с None, чтобы увидеть, является ли она одинаковой или нет.

Ответ 2

Как написано в PEP8:

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

    Кроме того, остерегайтесь писать "if x", когда вы действительно имеете в виду "если x не является None" - например. при проверке, является ли переменная или аргумент, по умолчанию Никому не было присвоено какое-либо другое значение. Другое значение может иметь тип (например, контейнер), который может быть ложным в булевом контексте!

Ответ 3

Множество функций возвращает None, если нет соответствующих результатов. Например, метод запроса SQLAlchemy .first() возвращает None, если в результате не было строк. Предположим, вы выбрали значение, которое могло бы возвращать 0, и нужно знать, действительно ли оно 0 или не было вообще никакого запроса.

Общая идиома заключается в том, чтобы дать опциональному аргументу функции или метода значение по умолчанию None, а затем проверить это значение как None, чтобы узнать, было ли указано. Например:

def spam(eggs=None):
    if eggs is None:
        eggs = retrievefromconfigfile()

сравните это с:

def spam(eggs=None):
    if not eggs:
        eggs = retrievefromconfigfile()

В последнем случае, если вы вызываете spam(0) или spam([])? Функция (неправильно) обнаружила бы, что вы не передали значение eggs и вычислили значение по умолчанию для вас. Возможно, это не то, что вы хотите.

Или представьте способ, например "вернуть список транзакций для данной учетной записи". Если учетная запись не существует, она может вернуть None. Это отличается от возврата пустого списка (что означает, что эта учетная запись существует, но не записала транзакции).

Наконец, вернемся к материалам базы данных. Там большая разница между NULL и пустой строкой. Пустая строка обычно говорит "там значение здесь, и это значение ничего не значит". NULL говорит, что "это значение не было введено".

В каждом из этих случаев вы хотите использовать if A is None. Вы проверяете конкретное значение - None - не просто "любое значение, которое происходит при нажатии на False".

Ответ 4

if x: #x is treated True except for all empty data types [],{},(),'',0 False, and None

поэтому он не такой, как

if x is not None # which works only on None

Ответ 5

если A: окажется ложным, если A равно 0, False или None, что может привести к нежелательным результатам.

Ответ 6

Большинство руководств, которые я видел, предлагают использовать

если A:

если у вас нет причин быть более конкретными.

Есть несколько незначительных отличий. Существуют значения, отличные от None, которые возвращают False, например пустые списки, или 0, поэтому подумайте о том, на что вы действительно тестируете.

Ответ 7

Это зависит от контекста.

Я использую if A:, когда я ожидаю, что A будет какой-то коллекцией, и я хочу только выполнить блок, если коллекция не пуста. Это позволяет вызывающему пройти любую коллекцию, состоящую из собственных вещей, пустую или нет, и заставить ее делать то, что я ожидаю. Он также позволяет None и False подавлять выполнение блока, что иногда удобно вызывать код.

OTOH, если я ожидаю, что A будет каким-то полностью произвольным объектом, но его можно было бы по умолчанию использовать None, тогда я всегда использовать if A is not None, поскольку код вызова мог бы сознательно пройти ссылка на пустую коллекцию, пустую строку или 0-значный числовой тип или логический False, или некоторый экземпляр класса, который в логическом контексте оказывается ложным.

И, с другой стороны, если я ожидаю, что A будет более определенной (например, экземпляр класса, который я собираюсь вызывать методы), но он мог бы быть по умолчанию None, и я считаю, что стандартное логическое преобразование является свойством класса, которое я не против принудительного исполнения во всех подклассах, тогда я просто использую if A:, чтобы сохранить мои пальцы страшную нагрузку при вводе дополнительных 12 символов.

Ответ 8

Они делают разные вещи.

Ниже проверяется, имеет ли A что угодно, кроме значений False, [], None, '' и 0. Он проверяет значение .

if A:

Ниже проверяется, является ли A другим объектом, кроме None. Он проверяет и сравнивает ссылку (адрес памяти) A и None.

if A is not None:

ОБНОВЛЕНИЕ: Дальнейшее объяснение

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

С учетом этих оптимизаций целые числа и строки одного и того же значения заканчиваются использованием того же пространства памяти. Вероятно, это объясняет, почему две отдельные строки действуют так, как будто они одинаковы.

> a = 'test'
> b = 'test'
> a is b
True
> a == b
True

Другие вещи не ведут себя одинаково, хотя..

> a = []
> b = []
> a is b
False
> a == b
True

У двух списков явно есть своя память. Удивительно кортежи ведут себя как строки.

> a = ()
> b = ()
> a is b
True
> a == b
True

Возможно, это связано с тем, что кортежи гарантированно не изменятся, поэтому имеет смысл повторно использовать одну и ту же память.

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

Ответ 9

None - это особое значение в Python, которое обычно обозначает неинициализированную переменную. Чтобы проверить, не использует ли данное значение данное значение, вы используете:

if A is not None

Значения Falsey - это особый класс объектов в Python (например, false, []). Чтобы проверить, является ли A ложным, используйте:

if not A

Таким образом, два выражения не одинаковы. И вам лучше не рассматривать их как синонимы.


P.S. Нет также ложно, поэтому первое выражение подразумевает второе. Но второй охватывает другие ложные значения, кроме Ничего. Теперь... если вы можете быть уверены, что не можете иметь другие значения false, кроме None в A, то вы можете заменить первое выражение на второе.

Ответ 10

Первый - более Pythonic (лучший идеоматический код), но не будет выполнять блок, если A - False (не None).

Ответ 11

python >= 2.6,

если мы пишем, например,

if A:

будет генерировать предупреждение как,

FutureWarning: поведение этого метода изменится в будущем версии. Используйте специальный тест "len (elem)" или "elem is not None" вместо этого.

Таким образом, мы можем использовать

if A is not None:

Ответ 12

Я создал файл под названием test.py и запустил его на интерпретаторе. Вы можете изменить то, что хотите, чтобы точно проверить, как все происходит за кулисами.

import dis

def func1():

    matchesIterator = None

    if matchesIterator:

        print( "On if." );

def func2():

    matchesIterator = None

    if matchesIterator is not None:

        print( "On if." );

print( "\nFunction 1" );
dis.dis(func1)

print( "\nFunction 2" );
dis.dis(func2)

Это различие ассемблера:

Источник:

>>> import importlib
>>> reload( test )

Function 1
  6           0 LOAD_CONST               0 (None)
              3 STORE_FAST               0 (matchesIterator)

  8           6 LOAD_FAST                0 (matchesIterator)
              9 POP_JUMP_IF_FALSE       20

 10          12 LOAD_CONST               1 ('On if.')
             15 PRINT_ITEM
             16 PRINT_NEWLINE
             17 JUMP_FORWARD             0 (to 20)
        >>   20 LOAD_CONST               0 (None)
             23 RETURN_VALUE

Function 2
 14           0 LOAD_CONST               0 (None)
              3 STORE_FAST               0 (matchesIterator)

 16           6 LOAD_FAST                0 (matchesIterator)
              9 LOAD_CONST               0 (None)
             12 COMPARE_OP               9 (is not)
             15 POP_JUMP_IF_FALSE       26

 18          18 LOAD_CONST               1 ('On if.')
             21 PRINT_ITEM
             22 PRINT_NEWLINE
             23 JUMP_FORWARD             0 (to 26)
        >>   26 LOAD_CONST               0 (None)
             29 RETURN_VALUE
<module 'test' from 'test.py'>