マジックメソッド

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__

==

selfother と等しい場合に True を返す。

__lt__

<

selfother より小さい場合に True を返す。

__le__

<=

selfother 以下の場合に True を返す。

__gt__

>

selfother より大きい場合に True を返す。

__ge__

>=

selfother 以上の場合に 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)

-

単項演算子 - による負数化を実装する。

チャレンジ:ベクトルクラスを作成する

あなたは、xyz という属性を持つ三次元ベクトルを表すクラス Vector を定義することを求められています。

このクラスには、ベクトルの加算、減算、およびドット積をそれぞれ行うための特殊メソッド __add____sub____mul__ の実装を含めるべきです。

これらに加えて、ベクトルの大きさを計算するためのメソッド magnitude を実装してください。

3d-vector.webp

要求されるメソッド:

  • __add__: このメソッドは他の Vector オブジェクトを受け取り、2つのベクトルの xyz 成分を加算した結果の新しい Vector を返すべきです。

  • __sub__: このメソッドは他の Vector オブジェクトを受け取り、最初のベクトルから2番目のベクトルの xyz 成分を減算した結果の新しい 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: 2 seconds

Memory limit: 512 MB

Output limit: 1 MB

To check your solution you need to sign in
Sign in to continue