You are here: Home > Dive Into Python > 内省の力 > and と or の奇妙な性質 | << >> | ||||
Dive Into PythonPython from novice to pro |
Python では, and と or は期待通りに論理演算を行いますが, 論理値を返すわけではありません. その代わりに, 論理演算を行っている実際の値のうちの 1 つを返します.
>>> 'a' and 'b' 'b' >>> '' and 'b' '' >>> 'a' and 'b' and 'c' 'c'
and を使うと, 左から右の順で論理値として値が評価されます. 0, '', [], (), {}, None は論理値としては偽で, 残りは全て真です. ただ, ほぼ全てです. デフォルトではクラスのインスタンスは論理値としては真ですが, 自作のクラスに特別なメソッドを作ることで, インスタンスを偽と評価させることができます. 5 章 でクラスや特別なメソッドについて全て学びます. 全ての値が論理値として真だった場合, and は最後の値を返します. この例では, and は 'a' を真, 'b' も真と評価し, 'b' を返します. | |
論理値として偽の値がある場合には, and は最初の偽の値を返します. この例では, '' が最初の偽の値です. | |
全ての値は真なので, and は最後の値 'c' を返します. |
>>> 'a' or 'b' 'a' >>> '' or 'b' 'b' >>> '' or [] or {} {} >>> def sidefx(): ... print "in sidefx()" ... return 1 >>> 'a' or sidefx() 'a'
あなたが C ハッカーなら, bool ? a : b という式 (bool が真なら a を, そうでなければ b を評価する) に馴染んでいるはずです. Python の and と or の振舞いのおかげで, 同じことができます.
>>> a = "first" >>> b = "second" >>> 1 and a or b 'first' >>> 0 and a or b 'second'
しかし, この Python の式は単に論理式で, 特別な言語の構造ではないので, この Python の and-or トリックと C の bool ? a : b 構文には決定的な違いがあります. a の値が偽の場合, 式はあなたが期待した通りには動きません. (私がこれにやられたことがあるのが分かるかい? 1 回より多いと思う?)
and-or トリック (bool and a or b) は, a が論理値として偽のときには C の bool ? a : b 式のようには動きません.
and-or トリックの裏に仕掛ける本物のトリックは a の値が絶対に偽にならないようにすることです. 1 つのよくあるやり方は a を [a] に, b を [b] に変え, 返り値のリストの最初の要素 (a または b) を取ることです.
ここまでで, このトリックは役に立つよりも問題の方が多そうに見えます. そもそも, if 文を使って同じ結果を得られるのに, 何故こんなどうでも良さそうなことを扱ったのでしょうか? まぁ多くの場合, あなたは 2 つの定数のうちどちらかを選ぼうとしているので, 単純な方の構文で十分で心配は要りません. なぜなら, a の値は常に真だと把握しているからです. そして, 複雑で安全な形を使う必要が出てきたとしても, そうする十分な理由があります. 例えば, lambda 関数の中など, Python には if 文が書けない場面があります.
(訳注. Python 2.5 から a if bool else b という構文がサポートされたので, その環境で開発する限りここで書かれているトリック無しでも C の三項演算子と同等のことが実現できます.)
<< リストのフィルター操作 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
lambda 関数を使う >> |