はじめに
このチュートリアルでは、Python の基本的なマジックメソッドを探ります。マジックメソッドは、「ダンダー」メソッド(ダブルアンダースコアメソッド)とも呼ばれ、特定の状況下で Python オブジェクトがどのように振る舞うかを定義し、高度なカスタマイズされたオブジェクト操作を可能にします。
このチュートリアルでは、Python の基本的なマジックメソッドを探ります。マジックメソッドは、「ダンダー」メソッド(ダブルアンダースコアメソッド)とも呼ばれ、特定の状況下で Python オブジェクトがどのように振る舞うかを定義し、高度なカスタマイズされたオブジェクト操作を可能にします。
このセクションでは、Python におけるオブジェクトの初期化と表現のマジックメソッドを探ります。これらのメソッドを使うことで、オブジェクトを作成する際のカスタムな動作を定義し、人間が読みやすく曖昧さのない文字列として表現することができます。
__init__ メソッドは、オブジェクトが作成されるときに呼び出されます。これは、オブジェクトの属性を初期化するために使用されます。
まずは簡単なオブジェクトから始めましょう。person.py で、2 つの属性を持つ Person という名前のクラスを作成します。
class Person:
def __init__(self, name: str, age: int):
"""
Initialize the Person object with a name and age.
:param name: The name of the person.
:param age: The age of the person.
"""
self.name = name
self.age = age
__str__ メソッドは、組み込み関数 str() と print() 関数によって呼び出され、オブジェクトの人間が読みやすい文字列表現を取得します。
#... (person.py の前のコード)
def __str__(self) -> str:
"""
Return a human-readable string representation of the Person object.
:return: A string describing the person.
"""
return f"{self.name} is {self.age} years old."
__repr__ メソッドは、組み込み関数 repr() によって呼び出され、インタラクティブなインタプリタで使用され、可能な限りオブジェクトを再作成するために使用できる文字列表現を取得します。
#... (person.py の前のコード)
def __repr__(self) -> str:
"""
Return a string representation of the Person object that can be used to recreate the object.
:return: A string in the format 'Person(name, age)'.
"""
return f"Person('{self.name}', {self.age})"
これで Person クラスの基本的なマジックメソッドを定義しましたので、init_repr_example.py でそれらがどのように機能するか見てみましょう:
from person import Person
## Create a new Person object
p = Person("Alice", 30)
## Use the __str__ method with the print function
print(p) ## Output: Alice is 30 years old.
## Use the __repr__ method in the interactive interpreter
print(repr(p)) ## Output: Person('Alice', 30)
そして、ターミナルで次のコマンドを入力してスクリプトを実行します。
python init_repr_example.py
このセクションでは、Python においてオブジェクトの比較に使用されるマジックメソッドを探ります。これらのメソッドを使うことで、自分たちのクラスのオブジェクトに対するカスタムな比較ロジックを定義することができます。
__eq__ メソッドは、2 つのオブジェクトが等しいかどうかを判定するために使用されます。== 演算子によって呼び出されます。
#... (person.py の前のコード)
def __eq__(self, other: "Person") -> bool:
"""
Compare two Person objects for equality.
:param other: The other Person object to compare with.
:return: True if both objects have the same name and age, False otherwise.
"""
if isinstance(other, Person):
return self.name == other.name and self.age == other.age
return False
__ne__ メソッドは、2 つのオブジェクトが等しくないかどうかを判定するために使用されます。!= 演算子によって呼び出されます。
#... (person.py の前のコード)
def __ne__(self, other: "Person") -> bool:
"""
Compare two Person objects for inequality.
:param other: The other Person object to compare with.
:return: True if the objects have different names or ages, False otherwise.
"""
return not self.__eq__(other)
__lt__ メソッドは、1 つのオブジェクトがもう 1 つのオブジェクトより小さいかどうかを判定するために使用されます。< 演算子によって呼び出されます。
#... (person.py の前のコード)
def __lt__(self, other: "Person") -> bool:
"""
Compare two Person objects to see if one is less than the other based on age.
:param other: The other Person object to compare with.
:return: True if the current object's age is less than the other object's age, False otherwise.
"""
if isinstance(other, Person):
return self.age < other.age
return NotImplemented
__le__ メソッドは、1 つのオブジェクトがもう 1 つのオブジェクト以下であるかどうかを判定するために使用されます。<= 演算子によって呼び出されます。
#... (person.py の前のコード)
def __le__(self, other: "Person") -> bool:
"""
Compare two Person objects to see if one is less than or equal to the other based on age.
:param other: The other Person object to compare with.
:return: True if the current object's age is less than or equal to the other object's age, False otherwise.
"""
if isinstance(other, Person):
return self.age <= other.age
return NotImplemented
__gt__ メソッドは、1 つのオブジェクトがもう 1 つのオブジェクトより大きいかどうかを判定するために使用されます。> 演算子によって呼び出されます。
#... (person.py の前のコード)
def __gt__(self, other: "Person") -> bool:
"""
Compare two Person objects to see if one is greater than the other based on age.
:param other: The other Person object to compare with.
:return: True if the current object's age is greater than the other object's age, False otherwise.
"""
if isinstance(other, Person):
return self.age > other.age
return NotImplemented
__ge__ メソッドは、1 つのオブジェクトがもう 1 つのオブジェクト以上であるかどうかを判定するために使用されます。>= 演算子によって呼び出されます。
#... (person.py の前のコード)
def __ge__(self, other: "Person") -> bool:
"""
Compare two Person objects to see if one is greater than or equal to the other based on age.
:param other: The other Person object to compare with.
:return: True if the current object's age is greater than or equal to the other object's age, False otherwise.
"""
if isinstance(other, Person):
return self.age >= other.age
return NotImplemented
これで Person クラスのオブジェクト比較のマジックメソッドを定義しましたので、compare_example.py でそれらがどのように機能するか見てみましょう:
from person import Person
## Create two Person objects
p1 = Person("Alice", 30)
p2 = Person("Bob", 35)
## Use the __eq__ and __ne__ methods
print(p1 == p2) ## Output: False
print(p1!= p2) ## Output: True
## Use the __lt__, __le__, __gt__, and __ge__ methods
print(p1 < p2) ## Output: True
print(p1 <= p2) ## Output: True
print(p1 > p2) ## Output: False
print(p1 >= p2) ## Output: False
そして、ターミナルで次のコマンドを入力してスクリプトを実行します。
python compare_example.py
このセクションでは、Python におけるオブジェクトの破棄のマジックメソッドを探ります。このメソッドを使うことで、オブジェクトが破棄されようとしているときのカスタムな動作を定義することができます。
__del__ メソッドは、オブジェクトが破棄されようとしているときに呼び出されます。これにより、オブジェクトがガベージコレクションされる前に、ファイルハンドルのクローズやリソースの解放などのクリーンアップタスクを実行することができます。
#... (person.py の前のコード)
def __del__(self):
"""
Clean up the Person object before it is destroyed.
"""
print(f"Person '{self.name}' is being deleted.")
これで Person クラスのオブジェクト破棄のマジックメソッドを定義しましたので、del_example.py でそれがどのように機能するか見てみましょう:
from person import Person
## Create a Person object and then delete it
p = Person("Alice", 30)
del p ## Output: Person 'Alice' is being deleted.
そして、ターミナルで次のコマンドを入力してスクリプトを実行します。
python del_example.py
重要なことは、オブジェクトが必要なくなったときに __del__ メソッドが必ずしも直ちに呼び出されるとは限らないことです。オブジェクトの実際の破棄は、Python インタプリタのガベージコレクションメカニズムに依存します。__del__ メソッドは、ガベージコレクタがオブジェクトをメモリから削除することを決定したときに呼び出されます。
この一連のチュートリアルでは、「ダンダー」メソッド(ダブルアンダースコアメソッド)とも呼ばれる Python のマジックメソッドを探りました。これらのメソッドを使うことで、さまざまな状況下でオブジェクトに対するカスタムな動作を定義することができます。
これらのマジックメソッドをマスターすることで、より強力でカスタマイズ可能な Python のクラスとオブジェクトを作成することができます。これらのメソッドを理解して実装することで、より効率的でクリーンな Python スタイルのコードを書くことができ、プログラムをより堅牢で保守しやすくすることができます。