Python `если х не None` или` если не х None`?

749

Я всегда думал, что if not x is Noneверсия будет более понятной, но руководство по стилю Google и PEP-8 используют оба if x is not None. Есть ли небольшая разница в производительности (я предполагаю, что нет), и есть ли случай, когда один действительно не подходит (делая другого явным победителем для моего соглашения)? *

* Я имею в виду любой синглтон, а не просто None.

... сравнивать синглтоны как None. Использование есть или нет.

orokusaki
источник
8
is notоператор сам по себе. Как !=. Если вы предпочитаете, not x is Noneто вы должны также предпочесть not a == bболее a != b.
Томаш Гандор
@ TomaszGandor У меня больше нет такого мнения not x is None(ответы здесь убедили меня) - однако стоит отметить, что not a == bэто предпочтительный стиль в Python по сравнению с a != b.
орокусаки
4
@orokusaki not a == bдействительно предпочитаемый стиль? Я никогда не видел, чтобы это делалось таким образом, и везде, куда я смотрю, люди все используют !=.
Майк - SMT
2
отсчеты читаемости @orokusaki В Python , так что это предпочтительный стиль , чтобы использовать один оператор !=вместо двух операторов not, ==.
Jeyekomon

Ответы:

995

Разницы в производительности нет, так как они компилируются в один и тот же байт-код:

Python 2.6.2 (r262:71600, Apr 15 2009, 07:20:39)
>>> import dis
>>> def f(x):
...    return x is not None
...
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> def g(x):
...   return not x is None
...
>>> dis.dis(g)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

Стилистически стараюсь избегать not x is y. Хотя компилятор всегда будет воспринимать это как not (x is y), читатель-человек может неправильно понять конструкцию как (not x) is y. Если я пишу, x is not yтогда нет никакой двусмысленности.

Даниэль Штутцбах
источник
103
Если только тот же читатель не думал, что это так x is (not y). Но я склонен согласиться с вами по другим причинам.
Etaoin
24
кроме того, «нет» является менее двусмысленным в этом контексте, «если a не равно None, а b равно None:« vs », если не a равно None, а b равно None:»
Гордон Ригли,
45
оператор должен быть "не"
боб
217

Как руководство по стилям Google, так и Python - лучшая практика:

if x is not None:
    # Do something about x

Использование not xможет привести к нежелательным результатам.

См. ниже:

>>> x = 1
>>> not x
False
>>> x = [1]
>>> not x
False
>>> x = 0
>>> not x
True
>>> x = [0]         # You don't want to fall in this one.
>>> not x
False

Вам может быть интересно посмотреть, какие литералы оцениваются Trueили Falseв Python:


Изменить для комментария ниже:

Я только что сделал еще несколько испытаний. not x is Noneне отрицает xсначала, а затем по сравнению с None. На самом деле, кажется, что isоператор имеет более высокий приоритет при использовании таким образом:

>>> x
[0]
>>> not x is None
True
>>> not (x is None)
True
>>> (not x) is None
False

Поэтому not x is Noneпросто, по моему честному мнению, лучше всего избегать.


Больше редактировать:

Я только что провел дополнительное тестирование и могу подтвердить, что комментарий Букзора правильный. (По крайней мере, я не смог доказать это иначе.)

Это средство if x is not Noneимеет точный результат как if not x is None. Я стою исправлено. Спасибо букзор.

Тем не менее, мой ответ остается в силе: используйте обычныеif x is not None .:]

Ксавье Хо
источник
131

Код должен быть написан, чтобы быть понятным программисту в первую очередь, а компилятор или интерпретатор - вторым. Конструкция «нет» больше напоминает английский, чем «не есть».

Марк Рэнсом
источник
33

Питон if x is not Noneили if not x is None?

TLDR: компилятор байт-кода анализирует их оба x is not None- так что для удобства чтения используйте if x is not None.

читабельность

Мы используем Python, потому что мы ценим такие вещи, как удобочитаемость, удобство использования и правильность различных парадигм программирования по сравнению с производительностью.

Python оптимизирует читабельность, особенно в этом контексте.

Разбор и компиляция байт-кода

В not связывает более слабо , чем is, так что нет никакой логической разницы здесь. Смотрите документацию :

Операторы isи is notпроверка на идентичность объекта: x is yистинно тогда и только тогда, когда x и y являются одним и тем же объектом. x is not yдает обратное значение истины.

Это is notспециально предусмотрено в грамматике Python как улучшение читаемости языка:

comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'

И поэтому это также унитарный элемент грамматики.

Конечно, это не разобрано так же

>>> import ast
>>> ast.dump(ast.parse('x is not None').body[0].value)
"Compare(left=Name(id='x', ctx=Load()), ops=[IsNot()], comparators=[Name(id='None', ctx=Load())])"
>>> ast.dump(ast.parse('not x is None').body[0].value)
"UnaryOp(op=Not(), operand=Compare(left=Name(id='x', ctx=Load()), ops=[Is()], comparators=[Name(id='None', ctx=Load())]))"

Но тогда байтовый компилятор фактически переведет not ... isв is not:

>>> import dis
>>> dis.dis(lambda x, y: x is not y)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE
>>> dis.dis(lambda x, y: not x is y)
  1           0 LOAD_FAST                0 (x)
              3 LOAD_FAST                1 (y)
              6 COMPARE_OP               9 (is not)
              9 RETURN_VALUE

Так что для удобства чтения и использования языка, как это было задумано, пожалуйста, используйте is not.

Не использовать это не разумно.

Аарон Холл
источник
« notСвязывает слабее, чем is, поэтому здесь нет логической разницы» - за исключением того, что Python не должен обеспечивать соблюдение логических и алгебраических идентификаторов (нет внутренней причины для (1 + 2)*3оценки так же, как 1*3 + 2*3). Здесь, очевидно, Python обманывает и оптимизирует UNARY_NOT.
Алексей
30

Ответ проще, чем делают люди.

Технического преимущества в любом случае не существует, и «x is y» - это то , что используют все остальные , что делает его очевидным победителем. Неважно, что это «больше похоже на английский» или нет; каждый использует его, что означает, что каждый пользователь Python - даже китайские пользователи, чей язык Python не похож на другой - поймет это с первого взгляда, где чуть менее распространенный синтаксис потребует парочку дополнительных мозговых циклов для анализа.

Не отличайтесь только ради того, чтобы быть другим, по крайней мере, в этой области.

Гленн Мейнард
источник
11

is notОператор предпочтительнее , чем отрицающий результат isпо стилистическим причинам. " if x is not None:" читает так же, как английский, но " if not x is None:" требует понимания приоритета оператора и не читает как английский.

Если есть разница в производительности, на которой лежат мои деньги is not, но это почти наверняка не является мотивацией для решения предпочесть эту технику. Очевидно, это будет зависеть от реализации. Поскольку isего нельзя переопределить, все равно должно быть легко оптимизировать любые различия.

Майк Грэм
источник
9

Лично я пользуюсь

if not (x is None):

что понимается сразу без двусмысленности каждым программистом, даже не разбирающимся в синтаксисе Python.

MikeTeX
источник
5
Справедливый аргумент, с которым я согласен, но я считаю, что аргумент следования идиоматическому стилю сильнее.
Щелчок
2

if not x is Noneбольше похож на другие языки программирования, но if x is not Noneопределенно звучит более четко (и более грамматически правильно на английском) для меня.

Тем не менее, мне кажется, что это больше для меня.

Davy8
источник
0

Я бы предпочел более читаемую форму, x is not y чем я думал бы, как в конечном итоге написать код обработки приоритета операторов, чтобы создать гораздо более читаемый код.

stefanogreg
источник