比較演算子

比較演算子

比較演算子の種類

 2 つのオブジェクト x, y を比較して、

 「 x と y は等しい?」
 「 x は y より大きい?」
 「 x は y に含まれる?」

などを判定して、True(真)または False(偽)の2択(真偽値)で答えさせる演算子を 比較演算子 (comparison operator) とよび、主に if 文などの条件判定式で用いられます。

 Python の比較演算子 には次のような種類があります。

比較演算子 True を返す条件
== x == y x と y が等しい
!= x != y x と y が等しくない
< x < y x が y より小さい
> x > y x が y より大きい
<= x <= y x が y 以下
>= x >= y x が y 以上
in x in y x が y に含まれている

 

比較演算子「==」

 実際に比較演算子「 == 」を使って戻り値を確認してみます。代入演算子の「 = 」と混同しないようにしてください。「 a = 1 」は「 a に 1 を代入する」というコードですが、「 a == 1 」は「 a が 1 に等しいときに True を返し、等しくないときは False を返す」というコードです。

 「 1 == 1 」は「 1 が 1 に等しいときは True を返し、等しくないときは False を返す」というコードなので、True を返しています。

#「1 と 1 は等しい」の真偽
print(1 == 1)
True

 「 1 == 2 」というコードを書くと、1 と 2 は等しくないので、False を返します。

#「1 と 2 は等しい」の真偽
print(1 == 2)
False

 「 != 」は被演算子同士が等しくないときに True を返し、等しいときに False を返すので、「 == 」とは真逆の結果が返ります。

#「1 と 1 は等しくない」の真偽
print(1 != 1)
False
#「1 と 2 は等しくない」の真偽:
print(1 != 2)
True

 

比較演算子「 > 」「 < 」「 >= 」「 >= 」

 「 > 」「 < 」「 >= 」「 >= 」はそれぞれ、「大きい」「小さい」「以上」「以下」を判定する演算子です。

# 「10は20以上である」の真偽
print(10 >= 20)
False

 10 は 20 以上ではないので、False が返っています。
 

比較演算子「in」

 「 in 」は文字列やリストのようなシーケンスに対して使われる演算子です。たとえば、Kobato という文字列の中に t が含まれるかどうか判定するコードは次のようになります。

# 「"Kobato"に"t"が含まれる」の真偽
print("t" in "Kobato")
True

 もちろん含まれているので、結果は True です。
 
 リストの場合も確認しておきましょう。

kobato_friend = ["真理子", "小春", "沙希"]

# 「kobato_friendに"小春"が含まれる」の真偽
x = "小春" in kobato_friend
print(x)
True

 リストの要素に "小春" があるので、True が返っています。
 

見て試してわかる機械学習アルゴリズムの仕組み 機械学習図鑑

新品価格
¥2,894から
(2019/8/6 11:45時点)

範囲内にあるかどうかを判定する

 Python では一度に 複数の比較演算子 を使って「 a < b < c 」のような書き方をすることができます。

# 「10は5より大きく20より小さい」の真偽
print(5 < 10 < 20)
True
# 「30は10より大きく20より小さい」の真偽
print(10 < 30 < 20)
False
# 「7と7と7が等しい」の真偽
print(7 == 7 == 7)
True

 こうした記法ができるのが Python の特徴で、複雑な条件分枝を扱うアルゴリズムもすっきりしたコードで表現できます。
 

文字列の比較

 比較演算子を使って文字列同士を比較することもできます。
 たとえば、"a" < "z" に対しては True が返ります。

#「"z"は"a"より大きい」の真偽
print("a" < "z")
True

 文字列は Unicode のコードポイントによって大小関係が定められています。
 コードポイントは組み込みの ord() 関数を使って確認できます。

# 文字列"a"のコードポイントを取得
cp_a = ord("a")

# 文字列"z"のコードポイントを取得
cp_z = ord("z")

print("a のコードポイント: {}".format(cp_a))
print("z のコードポイント: {}".format(cp_z))
a のコードポイント: 97
z のコードポイント: 122

 実行結果を見ると、"a" と "z" のコードポイントは、それぞれ 97, 122 なので、"z" のほうが "a" より大きいことになります。

 大文字 "A" と "Z" のコードポイントを調べてみましょう。

# 文字列"A"のコードポイントを取得
cp_A = ord("A")

# 文字列"Z"のコードポイントを取得
cp_Z = ord("Z")

print("A のコードポイント: {}".format(cp_A))
print("Z のコードポイント: {}".format(cp_Z))
A のコードポイント: 65
Z のコードポイント: 90

 このように、Unicode におけるアルファベットのコードポイントは

小文字のコードポイント = 大文字のコードポイント + 32

と定められているので、小文字と大文字を比較すると、小文字のほうが大きいと判定されます。

#「"a"は"A"より大きい」の真偽
print("A" < "a")
True

 複数の文字で構成される文字列同士を比較する場合、先頭の文字から順にチェックが行われます。たとえば、"abc" と "abd" を比較する場合、先頭から 2 文字目までは同じなので、"c" と "d" のコードポイントを比較して大小関係が決まります。

#「"abd"は"abc"より大きい」の真偽
print("abc" < "abd")
True

 文字数の異なる文字列同士も比較できます。 たとえば、"abc" と "ac" であれば、2 番目の文字同士を比べて、"ac" のほうが大きいと判定されます。

#「"ac"は"abc"より大きい」の真偽
print("abc" < "ac")
True

 "ab" と "abc" を比較する場合、3 番目の文字同士を比べることになりますが、"ab" には 3 番目の文字列はないので「値なし」となり、"abc" のほうが大きいと判定されます。

#「"abc"は"ab"より大きい」の真偽
print("ab" < "abc")
True

 

リスト(タプル)の比較

 リストやタプルにおいても大小関係が定められています (とはいえルールは極めて複雑です)。どちらも適用されるルールは同じなので、リストを使って説明します。

 リスト同士を比較する場合、先頭要素から順にチェックされて最初の異なる要素同士で大小関係が判定されます。たとえば、["x", "y", "w"] と ["x", "y", "z"] を比較すると、最初の 2 要素は同じなので、3 番目の要素同士を比較します。"z" は "w" よりも Unicode のコードポイントが大きいので (上述の「文字列の比較」を参照)、["x", "y", "z"] のほうが大きいことになります。

bf = ["x", "y", "w"] < ["x", "y", "z"]

print(bf)
True

 リストの要素数が互いに異なっていても比較は成立します。
 たとえば、["a", "b", "c"] と ["a", "d"] を比較すると、2 番目の要素同士で比較することになるので (3 番目の要素はチェックされない)、 ["a", "d"] のほうが大きいと判定されます。

bf = ["a", "b", "c"] < ["a", "d"]

print(bf)
True

 次は ["a", "b"] と ["a", "b", "c"] を比較してみましょう。
 最初の 2 要素は同じなので、3 番目の要素同士で比較することになりますが、["a", "b"] には 3 番目の要素がないので「値なし」とされて、["a", "b", "c"] のほうが大きいと判定されます。

tf = ["a", "b"] < ["a", "b", "c"]

print(tf)
True

 互いに異なる型の要素をもつリストを比較する場合、比較が成立する場合としない場合があります。たとえば、["a", "b"] と ["a", "c", 0] を比較した場合、2 番目の要素同士でチェックが行われるため、3 番目の要素は判定に無関係です。このようなケースでは比較が成立します。

tf = ["a", "b"] < ["a", "c", 0]

print(tf)
True

 しかし、["a", "b", "c"] と ["a", "b", 0] を比較した場合、3 番目の要素で判定が行われるので、型の違いによるエラー (TypeError) が送出されます。

tf = ["a", "b", "c"] < ["a", "b", 0]

print(tf)
'<' not supported between instances of 'str' and 'int'

 

比較演算子を定義する特殊メソッド

 自作クラスの内部の特殊メソッドを使ってオブジェクトの大小関係を定義できます。
 たとえば、__lt__() は「 < 」、__le__() は「 ≤ 」を定義します。

 例として質量データを表す Mass クラスを定義してみます。
 コンストラクタに値と単位を渡してオブジェクトを生成しますが、単位はキログラム (kg) またはポンド (b) のいずれかを選択できるようにします。

# In[1]

# 質量クラスを定義
class Mass:
    def __init__(self, value, unit="kg"):
        self.value = (value, unit)

        # 単位がbであればkgに換算
        if unit == "b":
            self.value_kg = 0.45359237 * value
        else:
            self.value_kg = value

    # 比較演算子「<」を定義
    def __lt__(self, other):
        return self.value_kg < other.value_kg

    # 比較演算子「<=」を定義
    def __le__(self, other):
        return self.value_kg <= other.value_kg

 インスタンス生成時にポンドを選択した場合、Mass クラスの内部でキログラム換算 (1 b = 0.45359237 kg) を行なって self.value_kg に格納します。キログラムを選択した場合は、value に渡した値をそのまま self.value_kg に格納します。比較演算子は self.value_kg 同士の大小関係によって定義されます。

 試しに、10 キログラムのオブジェクトを生成してみましょう。

# In[2]

# kg単位の質量オブジェクトを生成
m1 = Mass(10, "kg")

print(m1.value)
(10, 'kg')

 次に 20 ポンドのオブジェクトを生成します。

# In[3]

# ポンド単位の質量オブジェクトを生成
m2 = Mass(20, "b")

print(m2.value)
(20, 'b')

 10 キログラムと 20 ポンドを比較してみます。

# In[4]

# 10キログラムと20ポンドを比較
print(m1 < m2)
False

 20 ポンドは 10 キログラムに少し足りないので、m1 < m2 は False を返します。

 特殊メソッドで定義できる比較演算子をまとめておきます。

特殊メソッド 演算子
__lt__(self, other) <
__le__(self, other)
__eq__(self, other) ==
__ne__(self, other) !=
__gt__(self, other) >
__ge__(self, other)