マジックメソッド
Pythonでは、マジックメソッドはクラスに機能を追加するために定義できる特別なメソッドです。その名前の前後に二つのアンダースコア
__
が付くため、ダンダーメソッド(dunder methods)とも呼ばれます。これらのメソッドのうち、__init__
と __str__
の二つには既に出会っていることでしょう。簡単な例を見てみましょう:class Circle:
def __init__(self, radius): # オブジェクトを初期化する
self.radius = radius
def __str__(self): # 文字列として表現する
return f'Circle with radius {self.radius}'
c = Circle(5) # cという名前のCircleオブジェクトを作成する
print(c) # Circle with radius 5
この例では、2つのマジックメソッドを定義しています:
__init__
は、クラスのインスタンスが作成されるときに呼び出されるコンストラクタメソッドです。ここでは、Circleの半径を設定しています。
__str__
は、print()
などの文脈でクラスのインスタンスが文字列に変換される方法を定義します。
しかし、これらはPythonにおける唯一のマジックメソッドではありません。もっと多くのものがあります。以下に、クラスのインスタンスを
+
で足し合わせたり、<
や >
で比較できるようにするマジックメソッドのいくつかを示します:class Circle:
def __init__(self, radius): # オブジェクトを初期化する
self.radius = radius
def __str__(self): # 文字列として表現する
return f'Circle with radius {self.radius}'
def __add__(self, other): # 2つのCircleを加える
return Circle(self.radius + other.radius) # 新しいCircleを返す
def __lt__(self, other): # 2つのCircleを比較する(小なり)
return self.radius < other.radius # 半径を比較する
c1 = Circle(5)
c2 = Circle(7)
c3 = c1 + c2 # これは半径12の新しいCircleを作成する
print(c3) # Circle with radius 12
print(c1 < c2) # True
この場合:
__add__
は、Circleのインスタンスで+
演算子を使用できるようにします。これは、Circleの半径を加算し、新しいCircleを返します。
__lt__
(less than)は、<
演算子で2つのCircleインスタンスを比較できるようにします。これは、最初のCircleの半径が2番目の半径より小さいかどうかを確認します。
マジックメソッドを使うことで、Pythonのクラスはより表現力豊かで直感的になり、組み込みのPythonオブジェクトのように振る舞います。
特別な二重アンダースコアの命名を維持することを忘れないでください。Pythonのインタープリタは、特定の操作を実行するためにこれらの特別な名前のメソッドを探します。Pythonで利用可能なすべてのマジックメソッドのリストは、このリンクから見つけることができます。以下は、よく使われるマジックメソッドの一部です:
マジックメソッド | 演算子 | 説明 |
__eq__ | == | self が other と等しい場合に True を返す。 |
__lt__ | < | self が other より小さい場合に True を返す。 |
__le__ | <= | self が other 以下の場合に True を返す。 |
__gt__ | > | self が other より大きい場合に True を返す。 |
__ge__ | >= | self が other 以上の場合に True を返す。 |
__add__(self, other) | + | + 演算子による加算を実装する。 |
__sub__(self, other) | - | - 演算子による減算を実装する。 |
__mul__(self, other) | * | * 演算子による乗算を実装する。 |
__truediv__(self, other) | / | / 演算子による除算を実装する。 |
__floordiv__(self, other) | // | // 演算子による切り捨て除算を実装する。 |
__mod__(self, other) | % | % 演算子による剰余演算を実装する。 |
__pow__(self, other) | ** | 指数演算子 ** を実装する。 |
__abs__(self) | abs() | 組み込み関数 abs() の動作を実装する。 |
__round__(self, n) | round() | 組み込み関数 round() の動作を実装する。 |
__neg__(self) | - | 単項演算子 - による負数化を実装する。 |
💡
すべてのメソッドがすべてのクラスにとって意味があるわけではありません。あなたの問題に有用なものだけを実装してください。
チャレンジ:ベクトルクラスを作成する
あなたは、
x
、y
、z
という属性を持つ三次元ベクトルを表すクラス Vector
を定義することを求められています。このクラスには、ベクトルの加算、減算、およびドット積をそれぞれ行うための特殊メソッド
__add__
、__sub__
、__mul__
の実装を含めるべきです。これらに加えて、ベクトルの大きさを計算するためのメソッド
magnitude
を実装してください。要求されるメソッド:
__add__
: このメソッドは他のVector
オブジェクトを受け取り、2つのベクトルのx
、y
、z
成分を加算した結果の新しいVector
を返すべきです。
__sub__
: このメソッドは他のVector
オブジェクトを受け取り、最初のベクトルから2番目のベクトルのx
、y
、z
成分を減算した結果の新しいVector
を返すべきです。
__mul__
: このメソッドは他のVector
オブジェクトを受け取り、2つのベクトルのドット積を返すべきです。ドット積は $$(x1 \cdot x2) + (y1 \cdot y2) + (z1 \cdot z2)$$ として計算されます。
magnitude
: このメソッドはベクトルの大きさ(長さ)を返すべきです。大きさは $$\sqrt{x^2 + y^2 + z^2}$$ として計算されます。
入力 | 出力 |
v1 = Vector(1, 2, 3); v2 = Vector(4, 5, 6); v3 = v1 + v2; v4 = v1 - v2; print(v1 * v2); print(v1.magnitude()); v4 = Vector(-3, -3, -3) | 32
3.74165 |
Constraints
Time limit: 1 seconds
Memory limit: 512 MB
Output limit: 1 MB