Могу ли я использовать:
if A:
вместо
if A is not None:
Последнее кажется таким подробным. Есть ли разница?
Могу ли я использовать:
if A:
вместо
if A is not None:
Последнее кажется таким подробным. Есть ли разница?
Утверждение
if A:
вызовет A.__nonzero__()
(см. специальные имена методов) и используйте возвращаемое значение этой функции. Здесь резюме:
object.__nonzero__(self)
Вызывается для реализации тестирования истины и встроенной операции
bool()
; должен возвращатьFalse
илиTrue
, или их целые эквиваленты0
или1
. Когда этот метод не определен, вызывается__len__()
, если он определен, и объект считается истинным, если его результат отличен от нуля. Если класс не определяет ни__len__()
, ни__nonzero__()
, все его экземпляры считаются истинными.
С другой стороны,
if A is not None:
сравнивает только ссылку A
с None
, чтобы увидеть, является ли она одинаковой или нет.
Как написано в PEP8:
Сравнение с синглонами типа None всегда должно выполняться с помощью 'is' или 'is not', никогда не выполняются операторы равенства.
Кроме того, остерегайтесь писать "if x", когда вы действительно имеете в виду "если x не является None" - например. при проверке, является ли переменная или аргумент, по умолчанию Никому не было присвоено какое-либо другое значение. Другое значение может иметь тип (например, контейнер), который может быть ложным в булевом контексте!
Множество функций возвращает 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".
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
если A: окажется ложным, если A равно 0, False или None, что может привести к нежелательным результатам.
Большинство руководств, которые я видел, предлагают использовать
если A:
если у вас нет причин быть более конкретными.
Есть несколько незначительных отличий. Существуют значения, отличные от None, которые возвращают False, например пустые списки, или 0, поэтому подумайте о том, на что вы действительно тестируете.
Это зависит от контекста.
Я использую if A:
, когда я ожидаю, что A
будет какой-то коллекцией, и я хочу только выполнить блок, если коллекция не пуста. Это позволяет вызывающему пройти любую коллекцию, состоящую из собственных вещей, пустую или нет, и заставить ее делать то, что я ожидаю. Он также позволяет None
и False
подавлять выполнение блока, что иногда удобно вызывать код.
OTOH, если я ожидаю, что A
будет каким-то полностью произвольным объектом, но его можно было бы по умолчанию использовать None
, тогда я всегда использовать if A is not None
, поскольку код вызова мог бы сознательно пройти ссылка на пустую коллекцию, пустую строку или 0-значный числовой тип или логический False
, или некоторый экземпляр класса, который в логическом контексте оказывается ложным.
И, с другой стороны, если я ожидаю, что A
будет более определенной (например, экземпляр класса, который я собираюсь вызывать методы), но он мог бы быть по умолчанию None
, и я считаю, что стандартное логическое преобразование является свойством класса, которое я не против принудительного исполнения во всех подклассах, тогда я просто использую if A:
, чтобы сохранить мои пальцы страшную нагрузку при вводе дополнительных 12 символов.
Они делают разные вещи.
Ниже проверяется, имеет ли 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
читает как прозу, которую мы часто просто просматриваем.
None - это особое значение в Python, которое обычно обозначает неинициализированную переменную. Чтобы проверить, не использует ли данное значение данное значение, вы используете:
if A is not None
Значения Falsey - это особый класс объектов в Python (например, false, []). Чтобы проверить, является ли A ложным, используйте:
if not A
Таким образом, два выражения не одинаковы. И вам лучше не рассматривать их как синонимы.
P.S. Нет также ложно, поэтому первое выражение подразумевает второе. Но второй охватывает другие ложные значения, кроме Ничего. Теперь... если вы можете быть уверены, что не можете иметь другие значения false, кроме None в A, то вы можете заменить первое выражение на второе.
Первый - более Pythonic (лучший идеоматический код), но не будет выполнять блок, если A - False (не None).
python >= 2.6,
если мы пишем, например,
if A:
будет генерировать предупреждение как,
FutureWarning: поведение этого метода изменится в будущем версии. Используйте специальный тест "len (elem)" или "elem is not None" вместо этого.
Таким образом, мы можем использовать
if A is not None:
Я создал файл под названием 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'>