Python
基本データ型
文字列
比較

Python 文字列比較: __eq__(), 等しくない, 速度, 含む, アルゴリズム, 大文字小文字区別しない, 文字コード

この投稿では、Pythonの文字列の比較についてよくある質問をまとめました。

1. __eq__() メソッド

__eq__() メソッドは Python の特別なメソッドの 1 つで、2 つのオブジェクトが等しいかどうかを比較するために使用されます。 このメソッドは == 演算子で2つのオブジェクトを比較するときに単独で呼び出されます。 Python の文字列比較演算も == 演算子を使用するため、このメソッドを呼び出します。

つまり、"Hello" == "hello" を実行すると、Pythonは内部的に "Hello".__eq__("hello") を呼び出していることになります。

上のコードのように実行すると、2つの文字列が異なるという結果が得られます。

str1 = 'Hello'
str2 = 'hello'
 
print(str1 == str2) # output: False

これはPythonの文字列を表す組み込みクラスである str の内部で定義されている __eq__() メソッドは大文字と小文字を区別するからです。

したがって、 == 演算子を使用する Python 組み込みクラスは、そのクラスの内部で __eq__() メソッドが定義されていると言えます。 任意のクラスの __eq__() メソッドをオーバーライドすることで、 == 演算子の動作をカスタマイズすることができます。 このメソッドが存在しない場合、Pythonはデフォルトで2つのオブジェクトのメモリアドレスを比較します。

次の例では、大文字小文字を区別せずに比較を行う新しい文字列クラス CaseInsensitiveStr を定義しています。 メソッド __eq__() がどのように定義されているかに注意してください。

class CaseInsensitiveStr:
 
    def __init__(self, str_):
        self.str_ = str_.lower()
 
    def __eq__(self, other):
        if isinstance(other, CaseInsensitiveStr):
            return self.str_ == other.str_
        elif isinstance(other, str):
            return self.str_ == other.lower()
        return False
 
str1 = CaseInsensitiveStr('Hello')
str2 = CaseInsensitiveStr('hello')
 
print(str1 == str2) # output: True

2. 等しくない演算子を使う (>,<)

Python で文字列を比較するとき、not-equal 演算子は次の 2 つの目的で使えます。

  • 辞書的順序を示す
  • 包含関係を示す

2.1. 辞書順を示す非等号演算子

まず最初の目的から説明しましょう: Pythonは英数字の比較にはASCII値、ハングル文字の比較にはUnicode値(主に utf-8)を用います。

このようにアルファベット ab を比較する場合、実際にはこれら2つの文字のASCII値を比較しています。 ord()関数は与えられた文字のUnicodeコードポイント(ASCIIコードを含む)を返す組み込み関数です。

print("a" == "b") # this comparison is actually
print(ord("a") == ord("a")) # This comparison is true.

同じ原理で、文字列を比較するために >< のような not-equal 演算子を使うと、Unicode コードポイントの値を比較することになります。 これらの値はアルファベットと英数字の両方に対してアルファベット順にスケーリングされます。za よりも大きく、小文字は大文字よりも大きくなります。

print("a" < "z") # Output: True
print("A" < "a") # Output: True

2.2. 包含関係を表す非等号演算子

2つ目の用途は、文字列間の包含関係です。

Pythonは2文字以上の文字列を比較するとき、最も古い要素から1つずつ比較します。 ある文字列が別の文字列の部分文字列である場合、ある時点で文字とスペースを比較しなければならなくなります。 その時点で、長い方の文字列が大きいと判断される。

これをコードで見てみよう。

print("trees" > "tree") Output: True

tree" "trees" の部分文字列なので、常に小さい方の値として解決されます。

このことは、文字列の包含関係で not-equal 演算子を使うことを勧めるためではありません、 Pythonの文字列比較がどのように動作するかを説明するためです。 Pythonの文字列比較の仕組みを説明するためです。インクルードを決定するための強力なキーワード in があります。

3. Pythonの文字列比較アルゴリズムと時間複雑性

Pythonの文字列比較アルゴリズムは直感的です。 2つの文字列を比較するために、Pythonは同じインデックスの最初の2文字を比較します。

この結果、"hello" == "hellu" のように最大数の演算が必要な場合、 O(n) の時間複雑度になります。

4.2つの文字列を比較する際に大文字小文字を無視する方法

セクション1](#1)で述べたように、Pythonの str クラスは大文字小文字を区別するメソッド __eq__() を実装しています。 大文字小文字を区別せずに2つの文字列を比較したい場合は、 str クラスの upper() メソッドまたは lower() メソッドを使用します。

その名の通り、upper() メソッドは与えられた文字列の全ての文字を大文字にします、 lower()メソッドは与えられた文字列の文字を小文字に変換した新しい文字列を返します。 このため、大文字小文字を無視して比較を行うことが簡単にできます。

コードの例を見てみましょう。

lower_case = "happy"
mixed_case = "HaPPy"
 
print(lower_case == mixed_case) # output: False
print(lower_case.upper() == mixed_case.upper()) # output: True

これが、大文字小文字を区別しないPython文字列比較の結果を得る方法です。

5. 文字列とリストの比較

Python の文字列とリストは異なるデータ型なので、直接比較すると常に False を返します。

print(["a", "b", "c"] == "abc") # Output: False

つのデータ型の内容を比較するには、データ型を一致させる必要がある。そのためには、以下の2つのメソッドを使用します。

5.1. 文字列をリストに変換する list() 関数

最初のメソッドは文字列をリストに変換します。Pythonの list() 関数は、様々なデータ型をリストに変換するシンプルな関数です。

次のように使います。

print(list("abc")) # Output: ["a", "b", "c"]
print(["a", "b", "c"] == list("abc")) # output: True

データ型が同じなので、2つのリストの要素を比較して True を返しました。

5.2. リストを文字列に変換する join() メソッド

別の方法として、リストを文字列に変換してから比較することもできます。

これには join() メソッドを使用します。このメソッドはリストの全ての要素を1つの文字列に結合します。

print("".join(["a", "b", "c"])) # output: "abc"
print("".join(["a", "b", "c"]) == "abc") # Output: True

同じ文字列型を得たので、内容を比較できる。

6. まとめ

Pythonの文字列の比較についてよくある質問を5つ取り上げました。

copyright for Python 文字列比較: __eq__(), 等しくない, 速度, 含む, アルゴリズム, 大文字小文字区別しない, 文字コード

© 2023 All rights reserved.