私はこのようなコードのいくつかの例を見てきました:
if not someobj:
#do something
しかし、私はなぜしないのか疑問に思っています:
if someobj == None:
#do something
違いはありますか?一方が他方よりも有利ですか?
X != None?
私はこのようなコードのいくつかの例を見てきました:
if not someobj:
#do something
しかし、私はなぜしないのか疑問に思っています:
if someobj == None:
#do something
違いはありますか?一方が他方よりも有利ですか?
X != None?
回答:
最初のテストでは、Pythonはまだbool値になっていない場合、オブジェクトを値に変換しようとします。大まかに、私たちは目的を尋ねています:あなたは意味がありますか?これは、次のアルゴリズムを使用して行われます。
オブジェクトに__nonzero__特別なメソッドがある場合(数値組み込み関数やintとfloat同様)、このメソッドを呼び出します。bool直接使用されるint値、またはFalseゼロと等しいと見なされる値を返す必要があります。
オブジェクトがある場合はそれ以外の場合は、__len__(DOコンテナ組み込み関数など、特殊な方法でlist、dict、set、tuple、...)を、それがコンテナを考えると、このメソッドを呼び出しFalse、それは(長さがゼロである)空の場合。
それ以外の場合は、オブジェクトは考慮されますが、そうでTrueないNone場合は考慮されFalseます。
2番目のテストでは、オブジェクトがと等しいかどうか比較されNoneます。ここでは、オブジェクトに「この他の値と等しいですか?」と尋ねています。これは、次のアルゴリズムを使用して行われます。
オブジェクトに__eq__メソッドがある場合、それが呼び出され、戻り値が値に変換されて、boolの結果を決定するために使用されifます。
それ以外の場合、オブジェクトに__cmp__メソッドがある場合、それが呼び出されます。この関数intは、2つのオブジェクトの順序を示すを返す必要があります(-1if self < other、0if self == other、+1if self > other)。
それ以外の場合、オブジェクトの同一性が比較されます(つまり、isオペレーターがテストできるように、それらは同じオブジェクトへの参照です)。
is演算子を使用して別のテストが可能です。オブジェクトに「この特定のオブジェクトですか」と尋ねます。
一般に、最初のテストを数値以外の値で使用し、同じ性質のオブジェクト(2つの文字列、2つの数値など)を比較する場合の同等性のテストを使用し、次の場合にのみIDを確認することをお勧めします。センチネル値を使用する(例:Noneのメンバーフィールドに対して初期化されていないこと、getattrまたはまたは__getitem__メソッドを使用する場合)
要約すると、次のようになります。
>>> class A(object):
... def __repr__(self):
... return 'A()'
... def __nonzero__(self):
... return False
>>> class B(object):
... def __repr__(self):
... return 'B()'
... def __len__(self):
... return 0
>>> class C(object):
... def __repr__(self):
... return 'C()'
... def __cmp__(self, other):
... return 0
>>> class D(object):
... def __repr__(self):
... return 'D()'
... def __eq__(self, other):
... return True
>>> for obj in ['', (), [], {}, 0, 0., A(), B(), C(), D(), None]:
... print '%4s: bool(obj) -> %5s, obj == None -> %5s, obj is None -> %5s' % \
... (repr(obj), bool(obj), obj == None, obj is None)
'': bool(obj) -> False, obj == None -> False, obj is None -> False
(): bool(obj) -> False, obj == None -> False, obj is None -> False
[]: bool(obj) -> False, obj == None -> False, obj is None -> False
{}: bool(obj) -> False, obj == None -> False, obj is None -> False
0: bool(obj) -> False, obj == None -> False, obj is None -> False
0.0: bool(obj) -> False, obj == None -> False, obj is None -> False
A(): bool(obj) -> False, obj == None -> False, obj is None -> False
B(): bool(obj) -> False, obj == None -> False, obj is None -> False
C(): bool(obj) -> True, obj == None -> True, obj is None -> False
D(): bool(obj) -> True, obj == None -> True, obj is None -> False
None: bool(obj) -> False, obj == None -> True, obj is None -> True
これらは実際にはどちらも悪い習慣です。むかしむかし、NoneとFalseを同じように何気なく扱うことは問題ないと考えられていました。ただし、Python 2.2以降、これは最適なポリシーではありません。
あなたがやるときはまず、if xまたはif not xテストの種類を、Pythonは暗黙的に変換する必要がありxブールします。bool関数のルールは、Falseである多くのことを記述しています。それ以外はすべて真です。xの値がそもそも適切にブール値でなかった場合、この暗黙の変換は実際に言う最も明確な方法ではありません。
Python 2.2より前のバージョンでは、bool関数はなかったため、さらに不明確でした。
次に、実際にを使用してテストしないでください== None。とを使用する必要がis Noneありis not Noneます。
PEP 8、Style Guide for Python Codeを参照してください。
- 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。NotImplementedor を使用する可能性は非常に低くEllipsis、また言うこともないのでif x is True(単純if xである方がはるかに明確であるため)、テストするのはだけNoneです。
なぜならNone、偽りと見なされるのはそれだけではないからです。
if not False:
print "False is false."
if not 0:
print "0 is false."
if not []:
print "An empty list is false."
if not ():
print "An empty tuple is false."
if not {}:
print "An empty dict is false."
if not "":
print "An empty string is false."
False、0、()、[]、{}および""すべて異なっているNoneあなたの2つのコードスニペットがあるので、ないと同等。
さらに、次の点を考慮してください。
>>> False == 0
True
>>> False == ()
False
if object:等価チェックではありません。0、()、[]、None、{}、などです全て互いに異なるが、それらはすべて、評価 Falseに。
これは、次のような短絡式の背後にある「魔法」です。
foo = bar and spam or eggs
これは以下の略記です:
if bar:
foo = spam
else:
foo = eggs
あなたは本当に書くべきですが:
foo = spam if bar else egg
PEP 8 - Pythonのコードのためのスタイルガイドを使用することをお勧めしているかではありませんあなたはなしネスのためにテストしている場合
- Comparisons to singletons like None should always be done with 'is' or 'is not', never the equality operators.
一方、None-ness以上をテストする場合は、ブール演算子を使用する必要があります。
頼めば
if not spam:
print "Sorry. No SPAM."
スパムの__nonzero__メソッドが呼び出されます。Pythonマニュアルから:
__nonzero__(self)真理値テストと組み込みオペレーションbool();を実装するために呼び出されます。このメソッドが定義されていない場合、定義されていれば__len __()が呼び出されます(以下を参照)。クラスが__len __()も__nonzero __()も定義しない場合、そのインスタンスはすべてtrueと見なされます。
頼めば
if spam == None:
print "Sorry. No SPAM here either."
スパムの__eq__メソッドは、引数Noneで呼び出されます。
カスタマイズの可能性の詳細については、https: //docs.python.org/reference/datamodel.html#basic-customizationにあるPythonのドキュメントをご覧ください。
これら2つの比較は、異なる目的に役立ちます。前者は何かのブール値をチェックし、2番目はNone値のIDをチェックします。
答えは「場合によります」です。
このコンテキストでは、0、 ""、[]およびFalse(完全ではないリスト)がNoneと同等であると考える場合、最初の例を使用します。
個人的に、私は言語間で一貫したアプローチを選択しましたif (var)。varがbooleanとして宣言されている(またはCで特定の型がないなどのように定義されている)場合のみ、私は(または同等の)方法をとります。ここで誤って別の型を使用しないbように、これらの変数の前に(bVar実際にはそうなるように)を付けています。
ブール値への暗黙的なキャストはあまり好きではありません。複雑で複雑なルールが多数ある場合はなおさらです。
もちろん、人々は反対します。さらに進んif (bVar == true)でいる人もいますが、私の仕事のJavaコードで(私の趣味には冗長すぎます!)見えたり、あまりにもコンパクトな構文を愛しすぎたりwhile (line = getNextLine())(あいまいすぎたり)しています。