Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonの短絡評価(ショートサーキット)とは?and / or の意外な挙動を徹底解説

プログラミング初心者にありがちなつまずきポイントの一つが、ブール演算子(andor)の動作に対する誤解です。その原因は、Pythonインタプリタがこれらの式をどのような順序で評価しているのかを知らないことにあります。

たとえば、「and」と「or」を学んだばかりの頃は、次のような式を見て「変数Xが文字列 'x''y' のどちらかと一致するかどうかをチェックしているのだろう」と思い込みがちです。

X = ('x' or 'y')

しかし、実際にはそうではありません。本当に何が起きているのかを確かめるために、対話モードのインタプリタを起動して、以下の式を入力してみましょう。

>>> 'x' == ('x' or 'y')
True
>>> 'y' == ('x' or 'y')
False
>>> 'x' == ('x' and 'y')
False
>>> 'y' == ('x' and 'y')
True

一見すると、andor が壊れているようにさえ見えます。最初の2つの式では、'x'('x' or 'y') と一致するのに 'y' は一致しないのは不思議ですし、'y'('x' and 'y') と一致するのはなおさら謎に感じられるでしょう。

ところが、インタプリタがブール演算子をどのように処理しているのかを理解すれば、これらの結果はすべて「あなたが依頼した通りの動作」をしていることが分かります。ただし、あなたが意図していた内容とは別のことを実行しているだけなのです。

or 演算子の評価の仕組み

or 式の場合、Pythonインタプリタはまず最初の式(オペランド)を評価し、それが真(True)かどうかを調べます。最初の式が真であれば、Pythonは2番目の引数を一切見ずに、そのオブジェクトの値をそのまま返します。これは、or 式においては「どちらか一方でも真であれば式全体が真になる」ため、2番目の式を確認する必要がないからです。

逆に、最初の値が偽(False)と評価された場合は、今度は2番目の式を評価し、その値を返します。このとき、式全体の真偽は2番目の値によって決まります。

このように、インタプリタが必要最小限の評価しか行わない「怠け者」的な振る舞いは短絡評価(ショートサーキット評価)と呼ばれ、多くのプログラミング言語で採用されている一般的なブール式の評価方法です。

and 演算子の評価の仕組み

and 式でも同様に、短絡評価のテクニックを使って真偽値の判定を高速化しています。最初の式が偽であれば、式全体が必ず偽になるため、その時点でその値(偽)を返します。逆に最初の値が真であれば、2番目の式を評価してその値を返します。

それでは、インタプリタがコードを処理する過程で「何を見ているのか」を、4つのケースに分けて順番に追ってみましょう。

ケース1:'x' == ('x' or 'y')

'x' == ('x' or 'y')   # まず括弧の中を評価する → ('x' or 'y')
                      # 'x' は空でない文字列なので、最初の値は True
>>> 'x' == 'x'        # 文字列 'x' は文字列 'x' と等しいので、式全体は True
True

ケース2:'y' == ('x' or 'y')

'y' == ('x' or 'y')   # まず括弧の中を評価する → ('x' or 'y')
                      # 'x' は空でない文字列なので、最初の値は True
                      # 最初の値をそのまま返す → 'x'
'y' == 'x'            # 文字列 'y' は文字列 'x' と等しくないので、式は False

ケース3:'x' == ('x' and 'y')

>>> 'x' == ('x' and 'y')  # まず括弧の中を評価する → ('x' and 'y')
                          # 'x' は空でない文字列なので最初の値は True → 2番目の値を確認
                          # 'y' も空でない文字列なので、2番目の値も True
                          # 式全体の結果として2番目の値を返す → 'y'
>>> 'x' == 'y'            # 文字列 'x' は文字列 'y' と等しくないので、式は False
False

ケース4:'y' == ('x' and 'y')

>>> 'y' == ('x' and 'y')  # まず括弧の中を評価する → ('x' and 'y')
                          # 'x' は空でない文字列なので最初の値は True → 2番目の値を確認
                          # 'y' も空でない文字列なので、2番目の値も True
                          # 式全体の結果として2番目の値を返す → 'y'
>>> 'y' == 'y'            # 文字列 'y' は文字列 'y' と等しいので、式は True
True

短絡評価とは何か

短絡評価(ショートサーキット評価)とは、ANDOR のようなブール式を評価する際に、式を満たす、あるいは否定する最初の条件が見つかった時点で、残りの評価を打ち切ってよいという仕組みのことです。

公式ドキュメントでは、短絡評価について次のように説明されています。

操作結果説明
x or yx が偽なら y、そうでなければ x第1引数が偽の場合にのみ、第2引数(y)を評価する
x and yx が偽なら x、そうでなければ y第1引数(x)が真の場合にのみ、第2引数(y)を評価する
not xx が偽なら True、そうでなければ Falsenot は非ブール演算子よりも優先度が低い

短絡評価の実用的な活用例

この仕組みを理解しておくと、実務でも大いに役立ちます。たとえば、デフォルト値の設定によく使われる次のイディオムも、短絡評価の応用です。

name = user_input or '名無し'

user_input が空文字列や None(いずれも偽と評価される)の場合にのみ、右側の '名無し' が評価されて代入されます。同様に and を使えば、「オブジェクトが存在する場合にのみ属性へアクセスする」といった安全な処理を簡潔に記述できます。ブール演算子が「値を返す」という性質を押さえておけば、意図しないバグを防ぎ、よりPythonicなコードが書けるようになります。

  1. 【初心者向け】Pythonのissuperset()メソッドの使い方をわかりやすく解説

    はじめにこの記事では、Pythonのissuperset()メソッドについて、基本的な仕組みから実際のコード例まで詳しく解説します。issuperset()は、セット(集合)に対して使用できるメソッドで、引数として渡されたセットのすべての要素が、呼び出し元のセットに含まれているかどうかを判定します。呼び出し元のセットBが、引数のセットAのすべての要素を含んでいる場合 → True を返すセットAの要素がすべてBに含まれていない場合 → False を返すつまり、「BがAの上位集合(スーパーセット)であるかどうか」を判定するためのメソッドです。基本構文B.issuperset(A)この式は、Bが

  2. PythonでQuine(クワイン)プログラムを書いてみよう

    「Quine(クワイン)」とは、入力を一切受け取らずに、自分自身のソースコードを出力する特殊なプログラムのことです。一見すると不思議な自己言及的な仕組みですが、実装にはいくつかの厳格なルールがあります。最も重要な条件は、プログラム内部からソースコードファイルを読み込んではいけないという点です。つまり、純粋にコード自身の論理だけで自分の内容を再現しなければなりません。 サンプルコード Pythonでは、わずか1行でQuineを実現できます。 a=a=%r;print (a%%a);print (a%a) 実行結果 a=a=%r;print (a%%a);print (a%a) ご覧のとお