Pythono のリストには比較演算子が定義されています。




リストには比較演算子が定義されていて、 あたかも普通の int 型や float 型と同じように2 つのリストを比較することができます。

[0, 1, 2] == [0, 1, 2]  # True
[2, 3, 4] <= [3, 2, 5]  # True



この記事はプログラミング言語における とは何かについて考えるために書きました。 この記事は Python における値ってなに? のサブ記事です。

オブジェクトのPython ではやや抽象的な概念です: 例えば、オブジェクトの値にアクセスする正統な方法はありません。 また、その全てのデータ属性から構成されるなどの特定の方法で、オブジェクトの値を構築する必要性もありません。

比較演算子は、オブジェクトの とは何かについての特定の概念を実装しています。 この比較の実装によって、間接的にオブジェクトの を定義している 考えることもできます。
6.10.1. 値の比較



Python を習いたての方には「プログラミング言語における とは何か」や 「リストの比較演算子の詳細」という重箱の隅をつつくような話は、 あまりお役に立てないのではないかと思います。 ただ is と == の違いだけは、抑えておいた方が今後の学習の理解が進むかなと思います。

この記事では、まず良く使うリストの比較演算子について説明して、 そのあとあまり使うことのないリストの比較演算子を説明します。

いやいやリストの大小比較 >, < って何だよって感じですが、 そんなに難しいものではありません。大小比較 >, < は後半でご説明させていただきます。

# 良く使う
==
!=
is
is not
in
not in

# 滅多に使わない
<=
<
>=
>





よく使うもの ==, is, in, is not, not in

1. == 比較演算子

# 完全に同じなら True
# 123 == 123
[1, 2, 3] == [1, 2, 3]  # True

# 順番が違っていても False
# 123 == 132
[1, 2, 3] == [1, 3, 2]  # False

2. is 比較演算子

同じオブジェクトなら True になります。

2.1. 問題 1
# 1) 
a = [1, 2, 3]
b  # [1, 2, 3]
c = [1, 2, 3]

a is b  # 問題 1. True でしょうか False でしょうか


a is c  # 問題 2. True でしょうか False でしょうか
2.2. 解答 1

何故なら、変数 a と 変数 b には、同じオブジェクトが代入されているから。

>>> a is b  # 問題 1. True でしょうか False でしょうか
True
>>>


何故なら、変数 a と 変数 c には、別のオブジェクトが代入されているから

>>> a is c  # 問題 2. True でしょうか False でしょうか
False
>>> 
2.3. 問題 2

「値」を理解するにあたって == 比較演算子と is 比較演算子を区別することは大切です。 代入はコピーではありません。

a = [1, 2, 3]
b = a
c = [1, 2, 3]

# 変数 a に代入された
# オブジェクトの要素を1つ pop すると
a.pop()


# 問題 1.
#     1), 2) どちらが出力されるでしょうか?
b
"""
1) [1, 2, 3]
2) [1, 2]
"""


# 問題 2.
#     1), 2) どちらが出力されるでしょうか?
c
"""
1) [1, 2, 3]
2) [1, 2]
"""
2.4. 解答 2
>>> # 問題 1.
... #     1), 2) どちらが出力されるでしょうか?
... b
[1, 2]
>>> 
>>> # 問題 2.
... #     1), 2) どちらが出力されるでしょうか?
... c
[1, 2, 3]
>>> 




この問題は簡単そうに見えて実は結構、複雑です。 まず代入について復習して、次に is と == の違いを区別する必要があります。

Step 1. Python の変数と属性、代入とコピー
Step 2. Python の is と == の動作と違い




3. in 比較演算子

要素がリストに含まれているかを判定します。

1 in [1, 2, 3]  # True
4 in [1, 2, 3]  # False

4. is not, not in 比較演算子

ちなみに is not や not in は、それで1つの「比較演算子」になります。 not は単体で and や or と仲間の「ブール演算子」になります。
6.11. ブール演算 (boolean operation)

[1, 2, 3] is not [1, 2, 3]  # True
not [1, 2, 3] is [1, 2, 3]   # True
1 not in [1, 2, 3]  # False
not 1 in [1, 2, 3]  # False



あまり使わないもの <=, <, >=, >

リストの比較演算子の考え方は...



各要素は桁を表現しています。






リストの比較演算子とか in と == くらいしか使ったことがないので、>, < の重要性は低いかなと感じています。 こんなのもあるんだなくらいに押さえておいていただければと思います。

5. <= 比較演算子

# 123 <= 123
[1, 2, 3] <= [1, 2, 3]  # True

# 123 <= 124
[1, 2, 3] <= [1, 2, 4]  # True

# 423 <= 128
[4, 2, 3] <= [1, 2, 8]  # False

# 要素数が足りない方は -無限大が代入される
# 123(-無限大) < 123(-10)
[1, 2, 3] <= [1, 2, 3, -10]  # True

# 123(-10) <= 123(-無限大)
[1, 2, 3, -10] <= [1, 2, 3]  # False


リストの先頭の要素から順番に比較します。 もし2つの要素が同じ数なら次の要素を比較します。 シーケンス番号の小さい要素の大小比較が優先されます。

まず、最初の二つの要素を比較し、 その値が等しくなければその時点で比較結果が決まります。 等しければ次の二つの要素を比較し、 以降シーケンスの要素が尽きるまで続けます。
5.8. シーケンスとその他の型の比較



これと等価です。

from itertools import zip_longest
inf = float('inf')

# <=
def less_equal(lst1, lst2):
    for e1, e2 in zip_longest(lst1, lst2, fillvalue=-inf):
        if e1 == e2:
            continue
        elif e1 < e2:
            return True
        elif e1 > e2:
            return False
    return True


zip_longest は短い方のリストの要素を fillvalue で埋めてくれます。 そんなに重要な関数ではないので、覚える必要はありません。

# zip
#     短い方で止まる。
for e1, e2 in zip([1, 2], [1]):
    e1, e2

# (1, 1)
# zip_longest
#     仮引数 fillvalue で指定された値で埋めてくれる。
from itertools import zip_longest
inf = float('inf')

for e1, e2 in zip_longest([1, 2], [1], fillvalue=-inf):
    e1, e2

# (1, 1)
# (2, -inf)

6. < 比較演算子

これと等価です。

# <
def less_than(lst1, lst2):
    # return <= and not ==
    return less_equal(lst1, lst2) and not equal(lst1, lst2)

初等教育では <、> の「(等号を含まない)不等号」を先に導入するが、
数学一般においては等号を含めた
「≤」を先に定義する方が自然な場合が多く、
「<」のほうが「a ≤ b かつ a ≠ b」として定義される。
不等号 | Wikipedia

7. >= 比較演算子

省略

8. > 比較演算子

省略

余談: 不等号の定義のされ方について

Wikipedia の「「≤」を先に定義する方が自然な場合が多く...」というのは、 たしか包含関係を考える場合は、その方が良かった気がします。 字の汚さ、なんとかならないかな... 殴り書きなので流し読みしてください。

f:id:domodomodomo:20181218150639p:plain f:id:domodomodomo:20181218150646p:plain f:id:domodomodomo:20181218151347p:plain





list も値として大小関係 >, <, 等号 == が定義されていることがわかりました。 では、プログラミング言語における とは、そもそも一体何物なのでしょうか?