web-dev-qa-db-ja.com

pythonではNoneテストではない

これらのうち、なしテストはありません。

if val != None:

if not (val is None):

if val is not None:

どれが望ましいですか、そしてなぜですか?

577
prosseek
if val is not None:
    # ...

変数がNoneに設定されていないことをテストするためのPythonicの慣用句です。この慣用句は、 デフォルトのパラメータを使用してキーワード関数を宣言する場合に特に使用されますisはPythonでアイデンティティをテストします。実行中のPythonスクリプト/プログラムに存在するNoneのインスタンスは1つだけなので、isはこれに最適なテストです。 Johnsywebが指摘しているように 、これは PEP 8 の "Programming Recommendations"で議論されています。

なぜこれが好まれるのか

if not (val is None):
    # ...

これは単なるPythonの Zenの一部です :「読みやすさが重要です」。良いPythonはよく pseudocode に近いです。

828
gotgenes

から、プログラミングの推奨事項、 PEP 8

Noneのようなシングルトンとの比較は常に 'is'または 'is not'で行われるべきで、決して等価演算子ではありません。

また、「xがNoneではない場合」という意味のときは、「if x」を書くことに注意してください。デフォルトでNoneに設定されている変数または引数が他の値に設定されているかどうかをテストするとき。他の値には、ブール値のコンテキストではfalseになる可能性がある型(コンテナなど)があります。

PEP 8はどんなPythonプログラマーにとっても重要な読み物です。

93
Johnsyweb

後者2つのどちらでも、valは、Noneが渡されたときにtrueを返すように__eq__()を定義する型になる可能性があるためです。

これらの種類の質問に対する最善の策は、pythonが何をするのかを正確に見ることです。 disモジュールは非常に有益です。

>>> def f(val):
...   if val != None:
...     return True
...   return False
...
>>> def g(val):
...   if not (val is None):
...     return True
...   return False
...
>>> def h(val):
...   if val is not None:
...     return True
...   return False
...
>>> import dis
>>> dis.dis(f)
  2           0 LOAD_FAST                0 (val)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               3 (!=)
              9 POP_JUMP_IF_FALSE       16

  3          12 LOAD_GLOBAL              1 (True)
             15 RETURN_VALUE

  4     >>   16 LOAD_GLOBAL              2 (False)
             19 RETURN_VALUE
>>> dis.dis(g)
  2           0 LOAD_FAST                0 (val)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 POP_JUMP_IF_FALSE       16

  3          12 LOAD_GLOBAL              1 (True)
             15 RETURN_VALUE

  4     >>   16 LOAD_GLOBAL              2 (False)
             19 RETURN_VALUE
>>> dis.dis(h)
  2           0 LOAD_FAST                0 (val)
              3 LOAD_CONST               0 (None)
              6 COMPARE_OP               9 (is not)
              9 POP_JUMP_IF_FALSE       16

  3          12 LOAD_GLOBAL              1 (True)
             15 RETURN_VALUE

  4     >>   16 LOAD_GLOBAL              2 (False)
             19 RETURN_VALUE

最後の2つのケースは同じ一連の操作に帰着することに注意してください(pythonはnot (val is None)を読み、is not演算子を使用します)。 1つ目はNoneと比較するときに!=演算子を使います。

他の回答で指摘されているように、Noneと比較するときに!=を使うのは悪い考えです。

15
SheetJS