しゃちの備忘録

プログラミングを中心とした技術関連の備忘録です(今のところ)

Pythonにおける『and』と『or』の動作

Pythonの『and』と『or』の動作は, 他の言語と少し違う変わった動作をするのでそれについてメモ.

一般的な『and』と『or』の動作

bool型(True, またはFalse)の変数A, Bとしたときに,

A B A and B A or B
True True True True
True False False True
False True False True
False False False False

に, なります. ここでのポイントは, 『AとBはBool型のみである』ということです.

Pythonにおける『and』と『or』の動作①

では, Pythonではどのような動作になるか, まず入力の条件から書きます. 『AとBの型についての制限はありません』.

何を言っているのかと思うと思いますが, Pythonでのand,orAとBの型についての制限がないのです. これには, andorがそれぞれ行っている処理が深くかかわっています.

and の処理

Pythonandは以下のような処理を行います.

A and Bと書くとき, 第一引数A(第一引数) が偽なら A(第一引数), そうでなければ B(第二引数)

コードの形で記述すると以下のようになります.

if not bool(A):
    return A
else:
    return B

2種類の返値を見るとわかるように, 引数のどちらかをそのまま返しているのがわかると思います. ではここに示されているbool(A)では何が起こっているのでしょう.

Bool の処理

boolは基本的にどんなものでも真偽値判定を行ってくれます. ポイントとなるのが, 偽と見なされる以下の値達です.

  • None
  • False
  • 数値型におけるゼロ ( ex. 0, 0.0)
  • 空のシーケンス ( ex. '', (), [] )
  • 空のマッピング ( ex. {} )
  • ユーザ定義クラスのインスタンスで, bool() , len()メソッドを定義していて, 整数 0 または bool値 False を返すとき

逆にこれ以外のケースは全て真になります.

or の処理

Pythonorは以下のような処理を行います.

A or Bと書くとき, 第一引数A(第一引数) が偽なら B(第二引数), そうでなければ A(第一引数)

コードの形で記述すると以下のようになります.

if not bool(A):
    return B
else:
    return A

見た目はandと逆の構造になっています.

Pythonにおける『and』と『or』の動作②

上記のBoolの性質を理解したうえで, Pythonの場合のandの入出力の対応表を書くと以下の通りになります.(ちょっとだけ書き方自体も違うので読むとき注意)

それぞれのA,BをBoolにかけたときにどんな値が帰ってくるかも書いておきました. これを見るともともと真偽値表と同じ形になっていて, 正しくand , or として機能しているのがわかると思います.

bool(A) bool(B) A and B A or B
True True B(bool(B)->True) A(bool(A)->True)
True False B(bool(B)->False) A(bool(A)->True)
False True A(bool(A)->False) B(bool(B)->True)
False False A(bool(A)->False) B(bool(B)->False)

おまけ:サンプルコード

これの検証に書いたしょぼいコードですが置いておきます. 実行結果も合わせてどうぞ.

A  = ["abc", ""]
B  = ["xyz", ""]
for a in A:
  for b in B:
    print( "A(" + a + ")  or B(" + b + ") -> " + (a or b))

for a in A:
  for b in B:
    print( "A(" + a + ") and B(" + b + ") -> " + (a and b))
A(abc)  or B(xyz) -> abc
A(abc)  or B() -> abc
A()  or B(xyz) -> xyz
A()  or B() ->
A(abc) and B(xyz) -> xyz
A(abc) and B() ->
A() and B(xyz) ->
A() and B() ->