Pythonで次のようなものを書くと
foo==bar and spam or eggs
ブール文が true の場合、python はスパムを返し、それ以外の場合は卵を返すように見えます。誰かがこの動作を説明できますか? 式が長いブール値のように評価されないのはなぜですか?
編集:具体的には、式の結果として「スパム」または「卵」が返されるメカニズムを理解しようとしています。
Pythonで次のようなものを書くと
foo==bar and spam or eggs
ブール文が true の場合、python はスパムを返し、それ以外の場合は卵を返すように見えます。誰かがこの動作を説明できますか? 式が長いブール値のように評価されないのはなぜですか?
編集:具体的には、式の結果として「スパム」または「卵」が返されるメカニズムを理解しようとしています。
演算子andとorはショートサーキットです。つまり、式の結果が最初のオペランドのみの評価から推測できる場合、2 番目のオペランドは評価されません。たとえば、式があり、truea or bとa評価された場合、それが何であるかは関係ありません。b式の結果は true であるため、b評価されません。それらは実際には次のように機能します。
a and b: a が false の場合、b は評価されずに a が返されます。それ以外の場合は b が返されます。a or b: a が true の場合、b は評価されずに a が返されます。そうでない場合は b が返されます。Falsey と Truthy は、ブール値のコンテキストで false または true に評価される値を参照します。
ただし、このおよび/または慣用句は、より良い代替手段がなかった時代に役立ちましたが、現在はより良い方法があります:
spam if foo==bar else eggs
and/or イディオムの問題点は (初心者にとって混乱を招くことは別として)、条件が true であるにもかかわらず、spam が誤った値 (空の文字列など) に評価された場合に間違った結果が返されることです。このため、それを避ける必要があります。
これは、Python のブール演算子がどのように機能するかです。
ドキュメントから(最後の段落では、オペレーターがそのように動作することが良い考えである理由を説明しています):
ブール演算のコンテキストで、また制御フロー ステートメントで式が使用される場合、次の値は false として解釈されます:
False、None、すべての型の数値ゼロ、および空の文字列とコンテナー (文字列、タプル、リスト、辞書、セットを含む)およびフリーズセット)。他のすべての値は true として解釈されます。(__nonzero__()これを変更する方法については、特別な方法を参照してください。)演算子は、引数が false の場合に
not生成され、そうでない場合に生成されます。TrueFalse式
x and yは最初に評価されxます。が false の場合x、その値が返されます。それ以外の場合yは評価され、結果の値が返されます。式
x or yは最初に評価されxます。が true の場合x、その値が返されます。それ以外の場合、y が評価され、結果の値が返されます。(これらがおよびに返す値と型を制限し
andたり制限したりするのではなく、最後に評価された引数を返すことに注意してください。これは便利な場合があります。いずれにせよ値を発明しなければならないので、わざわざその引数と同じ型の値を返すことはないので、例えばyieldsではなく.)orFalseTruess or 'foo'notnot 'foo'False''
その理由は、Python が関係する変数の実際の値を使用してブール式を評価し、それらを値に制限するのではなく、評価するためTrueですFalse。次の値は false と見なされます。
NoneFalse'', (), [], {})__nonzero__()0 を返すまたは__len__()メソッドを使用したユーザー定義型False詳細については、Python ドキュメンテーションの真理値テストのセクションを参照してください。特に:
ブール値の結果を持つ演算および組み込み関数は、特に明記されていない限り、常にfalse および
0orを返します。(重要な例外: ブール演算とは常にオペランドの 1 つを返します。)False1Trueorand
括弧を使用して、式があいまいにならないようにしてください。そのままでは、次のようになります。
(foo == bar and spam) or eggs