HOWTO · Python

Python でタプルを比較する方法

この包括的なガイドで、Pythonでタプルを効果的に比較する方法を学びましょう。等値チェック、不等値チェック、辞書式比較など、さまざまな方法を紹介します。組み込み関数を使った要素ごとの比較方法も解説します。初心者でも経験豊富なプログラマーでも、実践的な例と明確な説明でコーディングスキルを高めることができます。

このページの内容

Pythonで作業していると、タプルを比較する必要がよくあります。タプルはイミュータブルなシーケンスであり、一度作成すると変更できません。この特性により、タプルは固定されたアイテムのコレクションを格納するのに特に便利です。タプルを比較することで、それらが等しいかどうか、順序、さらには内容を判断できます。

この記事では、単純な等値チェックから辞書式の順序付けまで、Pythonがタプルを比較する仕組みと、型、長さ、ネストが異なる場合に比較がどのように振る舞うかを紹介します。

Python がタプルを比較する仕組み

Pythonはタプルを辞書式に比較します。これは、辞書で単語が並ぶのと同じ方式です。各タプルの最初の要素を比較し、それらが異なれば、その最初の違いが比較の結果を決め、残りの要素は一切見られません。最初の要素が等しければ次のペアに進み、違いが見つかるか要素が尽きるまで続けます。一方のタプルが他方の接頭辞である場合、つまりそのすべての要素が長い方のタプルの先頭と一致する場合、短い方のタプルが長い方より小さいと見なされます。

等値演算子(==)は、両方のタプルが同じ要素を同じ順序で持っているかをチェックし、不等値演算子(!=)はその正反対です。

tuple1 = (1, 2, 3)
tuple2 = (1, 2, 3)
tuple3 = (1, 2, 4)

print(tuple1 == tuple2)
print(tuple1 == tuple3)
print(tuple1 != tuple3)

出力:

True
False
True

順序演算子(<、<=、>、>=)も同じ要素ごとの走査を行い、各ペア自体の順序を使って判断します。

tuple1 = (1, 2, 3)
tuple2 = (1, 2, 4)
tuple3 = (1, 2)

print(tuple1 < tuple2)
print(tuple1 > tuple3)

出力:

True
True

ここでtuple1がtuple2より小さいのは、最初の2つの要素が等しく、3 < 4だからです。また、tuple1がtuple3より大きいのは、tuple3がtuple1の接頭辞であり、長い方のタプルが短い方より後に並ぶからです。

異なる型、長さ、ネストしたタプルの扱い

等値と順序は、混在した型を同じようには扱いません。この2つを混同することは、誤った期待のよくある原因です。

等値は、型が原因でエラーを起こすことは決してありません。異なる型の2つの要素は単に等しくありません。ただし、1と1.0のような値は等しいと見なされるという、通常の数値の例外があります。そのため、==によるタプルの比較はFalseを返し、!=はTrueを返します。誰かが先に型をチェックするわけではありません。

tuple1 = (1, "a", 3)
tuple2 = (1, 2, 3)

print(tuple1 == tuple2)
print(tuple1 != tuple2)

出力:

False
True

順序はより厳格です。順序比較が、文字列と整数のように互いに順序付けできない要素のペアに到達した瞬間、結果を返す代わりにTypeErrorを発生させます。

tuple1 = (1, "a", 3)
tuple2 = (1, 2, 3)

print(tuple1 < tuple2)

出力:

TypeError: '<' not supported between instances of 'str' and 'int'

最初の要素は等しいため、比較は"a"と2に進みます。そして文字列と整数の間には順序がないため、エラーになります。なお、これは比較が実際に不一致のペアに到達した場合にのみ起こります。(0, "a") < (1, 2)はエラーなくFalseを返します。最初の要素ですでに決着がつくからです。

長さの違いは、よく使われる要素ごとの等値チェックと、見落としやすい形で相互作用します。all()とzip()を組み合わせると、zip()が生成するペアを比較しますが、zip()は短い方のタプルで停止します。そのため、対応のない末尾の要素は黙って無視されます。

tuple1 = (1, 2, 3)
tuple2 = (1, 2)

print(all(a == b for a, b in zip(tuple1, tuple2)))
print(len(tuple1) == len(tuple2) and all(a == b for a, b in zip(tuple1, tuple2)))

出力:

True
False

最初の行は、末尾の3が決して比較されないため、タプルが等しくないにもかかわらずTrueを報告します。このパターンを使う場合(大きなタプルや要素ごとのカスタムロジックに便利です)、2行目のように必ず長さのチェックと組み合わせてください。

ネストしたタプルに特別な扱いは不要です。タプル要素は、他の要素と同じルールで再帰的に比較されます。一方のタプルの中の(1, 2)は、もう一方の中の(3, 5)より前に並びます。それら自体の最初の異なる要素が決めるからです。

tuple1 = ((1, 2), (3, 4))
tuple2 = ((1, 2), (3, 5))

print(tuple1 < tuple2)
print(tuple1 == tuple2)

出力:

True
False

要するに、2つのタプルが同じかどうかだけを知りたい場合は==と!=を使ってください。これらはどんな内容でも機能します。相対的な順序が必要な場合は順序演算子を使い、比較が実際に到達する要素同士が順序付け可能であることを確認してください。