[解決!Python]if文にand/or演算子を使って複数の条件を記述するには:解決!Python
if文の条件として、複数の条件をand/or演算子を使ってひとまとめにして記述する方法や注意すべきポイントなどを紹介する。
* 本稿は2022年5月17日に公開された記事をPython 3.11.5で動作確認したものです(確認日:2023年9月11日)。
# 複数の条件が全て成立するかどうかをチェック:and演算子
a = 'foo'
b = 'bar'
if a == 'bar' and b == 'foo': # False and False == False
print('bar foo')
elif a == 'bar' and b == 'bar': # False and True == False
print('bar bar')
elif a == 'foo' and b == 'foo': # True and False == False
print('foo foo')
elif a == 'foo' and b == 'bar': # True and True == True
print('foo bar')
else:
print('other')
# 複数の条件のいずれかまたは全てが成立するかどうかをチェック:or演算子
a = 'foo'
b = 'bar'
if a == 'bar' or b == 'foo': # False or False == False
print('bar or foo')
elif a == 'bar' or b == 'bar': # False or True == True
print('bar or bar')
elif a == 'foo' or b == 'foo': # True and False == True
print('foo or foo')
elif a == 'foo' or b == 'bar': # True and True == True
print('foo or bar')
else:
print('other')
# 短絡評価
def f():
print('f called')
x = 1
if x == 1 and f(): # f called
pass
if x == 0 and f():
pass
if x == 1 or f():
pass
if x == 0 or f(): # f called
pass
# 3つ以上の条件(and演算子とor演算子の組み合わせ)
values = [(150, 200, 100), (200, 300, 100), (0, 0, 300)]
for x, y, z in values:
if 100 <= x and 300 <= y or 200 < z:
print('foo')
else:
print('bar')
# 出力結果:
# bar
# foo
# foo
# 演算子の優先順位
a, b, c = 2, 1, 0
if result := a or b and c: # and > orなので「b and c」が先に評価される
print('True:', result)
else:
print('False:', result)
# 出力結果:
# True: 2
if result := not a or b and c: # 「not a」「b and c」「結果1 or 結果2」の順
print('True:', result)
else:
print('False:', result)
# 出力結果:
# False: 0
# and演算子を省略
# and演算子を省略していない書き方
n = 156
if 0 <= n and n < 100: # どちらも不成立
print('0 <= n < 100')
elif 100 <= n and n < 150: # 一方だけが成立
print('100 <= n < 150')
elif 150 <= n and n < 200: # どちらも成立
print('150 <= n < 200')
# 上のコードは下のようにも書ける
n = 156
if 0 <= n < 100: # どちらも不成立
print('0 <= n < 100')
elif 100 <= n < 150: # 一方だけが成立
print('100 <= n < 150')
elif 150 <= n < 200: # どちらも成立
print('150 <= n < 200')
複数の条件が全て成立するかどうかをチェック:and演算子
if文で条件分岐をする際に、複数の条件が成立しているかどうかや、複数の条件のいずれかが成立しているかどうかがポイントになることがある。こうしたときには、and/or演算子を用いて、複数の条件をまとめて記述できる。
- and演算子:複数の条件が全て成立(True、真)のときにTrue(真)となる
- or演算子:複数の条件のいずれか1つでも成立すればTrueとなる(全ての条件の値がTrueでもよい)
複数の条件全てが成立したときに特定の処理を実行したければ、if文の条件として「式0 and 式1 and …… and 式n」のように条件を記述する式をand演算子でつないで記述する。and演算子では、その両側にある2つの式が共に成立すれば、全体としての条件が成立して、その値がTrueとなる。日本語で読み下すときには「and」は「かつ」と読める。
以下に例を示す。これは変数aとbの値と文字列'foo'と'bar'とを比較している。
a = 'foo'
b = 'bar'
if a == 'bar' and b == 'foo': # False and False == False
print('bar foo')
elif a == 'bar' and b == 'bar': # False and True == False
print('bar bar')
elif a == 'foo' and b == 'foo': # True and False == False
print('foo foo')
elif a == 'foo' and b == 'bar': # True and True == True
print('foo bar')
else:
print('other')
この例では、if文で上から順に以下の条件をテストしている。
- a == 'bar' and b == 'foo':変数aの値が'bar'「かつ」変数bの値が'foo'かどうか
- a == 'bar' and b == 'bar':変数aの値が'bar'「かつ」変数bの値が'bar'かどうか
- a == 'foo' and b == 'foo':変数aの値が'foo'「かつ」変数bの値が'foo'かどうか
- a == 'foo' and b == 'bar':変数aの値が'foo'「かつ」変数bの値が'bar'かどうか
一方、if文の前で変数aには'foo'が、変数bには'bar'が代入されている。よって、「a == 'foo'」「b == 'bar'」の2つand演算子でつないでいる最後の条件が全体としては真となり、他の条件はFalseとなる。結果、最後のelif節のコードが実行され「foo bar」と表示される。
複数の条件のいずれかまたは全てが成立するかどうかをチェック:or演算子
複数の条件のいずれかまたは全てが成立したときに特定の処理を実行したければ、if文の条件として「式0 or 式1 or …… or 式n」のように条件を記述する式をor演算子でつないで記述する。or演算子では、その両側にある2つの式のいずれかが成立すれば、全体としての条件が成立して、その値がTrueとなる。日本語で読み下すときには「or」は「または」と読める。
以下に例を示す。先ほどと同様、変数aとbの値と文字列'foo'と'bar'とを比較している。
a = 'foo'
b = 'bar'
if a == 'bar' or b == 'foo': # False or False == False
print('bar or foo')
elif a == 'bar' or b == 'bar': # False or True == True
print('bar or bar')
elif a == 'foo' or b == 'foo': # True and False == True
print('foo or foo')
elif a == 'foo' or b == 'bar': # True and True == True
print('foo or bar')
この例では、if文で上から順に以下の条件をテストしている。
- a == 'bar' or b == 'foo':変数aの値が'bar'「または」変数bの値が'foo'かどうか
- a == 'bar' or b == 'bar':変数aの値が'bar'「または」変数bの値が'bar'かどうか
- a == 'foo' or b == 'foo':変数aの値が'foo'「または」変数bの値が'foo'かどうか
- a == 'foo' or b == 'bar':変数aの値が'foo'「または」変数bの値が'bar'かどうか
一方、if文の前で変数aには'foo'が、変数bには'bar'が代入されている。よって、最初の条件である「a == 'bar' or b == 'foo'」のみは2つの条件がどちらも成立しないので、全体としても評価結果はFalseとなるが、他の条件についてはいずれか、もしくは両方が成立するのでTrueとなる。結果、2つ目の条件が成立した際に「bar or bar」と表示され、if文の実行が終了する。
短絡評価
and演算子やor演算子では、その両側にある2つの式が両方とも実行されるとは限らない。というのは、and演算子は2つの条件が「どちらもTrue」であるときにその結果がTrueとなる。そのため、最初に評価される条件(左側の式)の値がFalseとなった時点で条件全体の値がFalseとなることが決まる。この場合、もう1つの条件を評価する意味はないので、その条件は評価されない。こうした処理のことを「短絡評価」と呼ぶことがある。
以下に例を示す。
def f():
print('f called')
x = 1
if x == 1 and f(): # f called
pass
if x == 0 and f():
pass
この例では呼び出されると「f called」と表示するだけの関数を定義して、if文の条件として、and演算子の右側(2番目に評価される条件)にその関数呼び出しを記述している。
最初のif文では、「x == 1」と「f()」がand演算子でつながれている。つまり、全体としての条件は「x == 1かつf関数の呼び出し結果が真かどうか」である(ただし、f関数は何も返さないのでこの条件自体は成立しない。が、ここでは本題とは関係ない)。このとき、「x == 1」という条件は成り立つので、もう1つの条件である「f()」が実行されて、コンソールには「f called」と表示されるはずだ。
次のif文では、「x == 0」を評価した時点で、その結果がFalseなのでf関数を呼び出さずとも、全体の値がFalseであることが決まる。そのため、f関数は呼び出されず「f called」とも表示されない。
or演算子でも同様で、最初に評価される条件(左側の式)の値がTrueとなった時点で、全体としての条件はTrueとなることが決まる。このときには、やはりもう1つの条件は評価されない。
以下に例を示す。or演算子では1つ目の条件がFalseのときに、全体としての条件がTrueとなるかどうかをテストする必要があるので、2つ目のif文でf関数が呼び出されることに注意されたい。
if x == 1 or f():
pass
if x == 0 or f(): # f called
pass
3つ以上の条件(and演算子とor演算子の組み合わせ)
and/or演算子を組み合わせて、より複雑な条件を組み立てることも可能だ。以下に例を示す(ただし、この条件自体に深い意味はない。and/or演算子の組み合わせを例示するだけのものだ)。
values = [(150, 200, 100), (200, 300, 100), (0, 0, 300)]
for x, y, z in values:
if 100 <= x and 300 <= y or 200 < z:
print('foo')
else:
print('bar')
「100 <= x and 300 <= y or 200 < z」という条件について考えてみると、最初の数値の組(150, 200, 100)では「100 <= x」はTrue、「300 <= y」はFalse、「200 < z」はFalseとなる。つまり、この条件式は全体としては「True and False or False」となる。and演算子とor演算子では、and演算子の方が優先順位が高く先に評価されるので、この式は「(True and False) or False」として考えられる。かっこ内の「True and False」の値は「False」なので、最終的には「False or False」=「False」がこの条件の値となり、else節が実行されて、「bar」と表示される
次の組は「100 <= 200 and 300 <= 300 or 200 < 100」つまり「True and True or False」=「True」となる。最後の組は「100 <= 0 and 300 <= 0 or 200 < 300」つまり「False and False or True」=「True」となる。
演算子の優先順位
上でも述べたが、and演算子の方がor演算子よりも優先順位が高いことには注意しよう。
以下に例を示す。なお、この例では、and演算子とor演算子は最後に評価した式の値を返すことと、0はFalseと見なされてそれ以外の値はTrueと見なされることを利用している。また、「result := ……」として条件の評価結果を変数resultに代入もしている。
a, b, c = 2, 1, 0
if result := a or b and c: # and > orなので「b and c」が先に評価される
print('True:', result)
else:
print('False:', result)
# 出力結果:
# True: 2
この例では、変数a、b、cにはそれぞれ2、1、0が代入されている。そして、if文の条件は「a or b and c」だ。つまり、「2 or 1 and 0」となる。既に述べた通り、and演算子の方が高い優先順位なので、まずは「1 and 0」が評価されて「0」となる。次にこの結果を使って「2 or 0」が評価される。そのため、結果は2となる。
if result := not a or b and c: # 「not a」「b and c」「結果1 or 結果2」の順
print('True:', result)
else:
print('False:', result)
# 出力結果:
# False: 0
こちらの例は上の条件式の先頭に「not」が付いただけだ。よって、「not 2 or 1 and 0」である。not演算子はand演算子よりも優先順位が高いので「not 2」が最初に評価されて「False or 1 and 0」となる。その次に、and演算子の評価が行われるのは先ほどと同様で「False or 0」となる。この式がTrueとなるかは右側の被演算子である「0」を評価するまでは分からない。そのため、これが評価されて、この条件式全体の値として返される。そのため、結果は0となる。
and/or演算子を組み合わせるときには優先順位に注意すること(演算の順序を明示的に指定するには、優先順位を高くしたい部分をかっこ「()」で囲むこともできるので覚えておこう)。
and演算子を省略
Pythonでは、多数の条件をand演算子でつないだ場合、andを省略できる。といっても分かりづらいので以下に例を示す。
n = 156
if 0 <= n and n < 100: # どちらも不成立
print('0 <= n < 100')
elif 100 <= n and n < 150: # 一方だけが成立
print('100 <= n < 150')
elif 150 <= n and n < 200: # どちらも成立
print('150 <= n < 200')
これは変数nの値が特定の範囲に収まるかをチェックするコードだ。「0 <= n and n < 100」のように複数の比較式をandでつないでいることが分かる。だが、このコードは以下のようにも書ける。
n = 156
if 0 <= n < 100: # どちらも不成立
print('0 <= n < 100')
elif 100 <= n < 150: # 一方だけが成立
print('100 <= n < 150')
elif 150 <= n < 200: # どちらも成立
print('150 <= n < 200')
数学の教科書などでよく見られる記述だ。こちらの方が見やすくスッキリとしたコードとなる。
Pythonでは、変数a、b、c、dがあるとして「a op0 b and b op1 c and c op2 d」(op0〜op2は2項の比較演算子)という条件式は「a op0 b op1 c op2 d」のように書けるということだ。上のように変数の値が特定の範囲に含まれるかのチェックで使うのが一般的かもしれないが、実際にはどのような比較演算子であってもこのような記述が可能だ。
x, y, z = 10, 20, 30
if x < y > z:
print('x < y and y > z')
else:
print('not x < y > z')
分かりづらいが、このような条件も問題なく書ける。この機能を使うときには、何を比較しようとしているのかを明確に書けるときだけにすることをオススメする。
Copyright© Digital Advantage Corp. All Rights Reserved.