Pythonでの算術演算子: 足し算、引き算、掛け算、割り算と特殊メソッドの利用

Pythonには、`+`、`-`、`*`、`/`などの基本的な算術演算子がありますが、これらの演算子の背後では、特殊メソッド（ダンダーメソッド）が動作しています。

### 足し算 `+`と `__add__` メソッド
足し算演算子 `+` は、内部的に `__add__` メソッドを呼び出して動作しています。これは、Pythonの組み込み型や、独自に定義したクラスでも使用できます。

- 基本の足し算

```python
a = 5
b = 3
result = a + b  # 内部では a.__add__(b) が呼ばれる
print(result)  # 出力: 8
```

- `__add__` メソッドを使ったクラス

```python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    # 足し算のための __add__ メソッドを定義
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    def __str__(self):
        return f"Point({self.x}, {self.y})"

# 2つのPointオブジェクトを作成
p1 = Point(2, 3)
p2 = Point(4, 1)

# + 演算子でオブジェクトを加算
p3 = p1 + p2  # 内部で p1.__add__(p2) が呼ばれる
print(p3)  # 出力: Point(6, 4)
```

### 引き算（-）と `__sub__` メソッド

- 基本の引き算

```python
a = 5
b = 3
result = a - b  # 内部では a.__sub__(b) が呼ばれる
print(result)  # 出力: 2
```

- `__sub__` メソッドを使ったクラス

```python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    # 引き算のための __sub__ メソッドを定義
    def __sub__(self, other):
        return Point(self.x - other.x, self.y - other.y)

    def __str__(self):
        return f"Point({self.x}, {self.y})"

p1 = Point(5, 7)
p2 = Point(2, 3)

# - 演算子でオブジェクトを減算
p3 = p1 - p2  # 内部で p1.__sub__(p2) が呼ばれる
print(p3)  # 出力: Point(3, 4)
```

掛け算（*）と `__mul__` メソッド

- 基本の掛け算

```python
a = 5
b = 3
result = a * b  # 内部では a.__mul__(b) が呼ばれる
print(result)  # 出力: 15
```

- `__mul__` メソッドを使ったクラス

```python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    # 掛け算のための __mul__ メソッドを定義
    def __mul__(self, other):
        return Point(self.x * other.x, self.y * other.y)

    def __str__(self):
        return f"Point({self.x}, {self.y})"

p1 = Point(3, 4)
p2 = Point(5, 6)

# * 演算子でスカラー倍
p_scaled = p1 * p2  # 内部で p1.__mul__(p2) が呼ばれる
print(p_scaled)  # 出力: Point(15, 24)
```

割り算（/）と `__truediv__` メソッド

- 基本の割り算
- 
```python
a = 9
b = 3
result = a / b  # 内部では a.__truediv__(b) が呼ばれる
print(result)  # 出力: 3.0
```

- `__truediv__` メソッドを使ったクラス

```python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    # 割り算のための __truediv__ メソッドを定義
    def __truediv__(self, other):
        return Point(self.x / other.x, self.y / other.y)

    def __str__(self):
        return f"Point({self.x}, {self.y})"

p1 = Point(6, 8)
p2 = Point(3, 2)
# / 演算子でスカラー除算
p_scaled = p1 / p2  # 内部で p1.__truediv__(p2) が呼ばれる
print(p_scaled)  # 出力: Point(2.0, 4.0)
```

### まとめ

Pythonでは、算術演算子を使って簡単に数値計算を行うことができます。また、__add__や__sub__などの特殊メソッドを使えば、クラスに対して独自の演算子の動作を定義することも可能です。

```python
class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        
    # 足し算のための __add__ メソッドを定義
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    # 引き算のための __sub__ メソッドを定義
    def __sub__(self, other):
        return Point(self.x - other.x, self.y - other.y)

    # 掛け算のための __mul__ メソッドを定義
    def __mul__(self, other):
        return Point(self.x * other.x, self.y * other.y)

    # 割り算のための __truediv__ メソッドを定義
    def __truediv__(self, other):
        return Point(self.x / other.x, self.y / other.y)

    def __str__(self):
        return f"Point({self.x}, {self.y})"

print(Point(3,4))  # 出力: Point(3, 4) 
print(Point(3,4)+Point(2,8))  # 出力: Point(5, 12) 
print(Point(3,4)-Point(2,8))  # 出力: Point(1, -4) 
print(Point(3,4)*Point(2,8))  # 出力: Point(6, 32) 
print(Point(3,4)/Point(2,8))  # 出力: Point(1.5, 0.5)   
```

### 参考

[他の特殊メソッド](https://docs.python.org/ja/3/reference/datamodel.html#emulating-container-types)

```
object.__add__(self, other)
object.__sub__(self, other)
object.__mul__(self, other)
object.__matmul__(self, other)
object.__truediv__(self, other)
object.__floordiv__(self, other)
object.__mod__(self, other)
object.__divmod__(self, other)
object.__pow__(self, other[, modulo])
object.__lshift__(self, other)
object.__rshift__(self, other)
object.__and__(self, other)
object.__xor__(self, other)
object.__or__(self, other)
```

```
object.__radd__(self, other)
object.__rsub__(self, other)
object.__rmul__(self, other)
object.__rmatmul__(self, other)
object.__rtruediv__(self, other)
object.__rfloordiv__(self, other)
object.__rmod__(self, other)
object.__rdivmod__(self, other)
object.__rpow__(self, other[, modulo])
object.__rlshift__(self, other)
object.__rrshift__(self, other)
object.__rand__(self, other)
object.__rxor__(self, other)
object.__ror__(self, other)
```

```
object.__iadd__(self, other)
object.__isub__(self, other)
object.__imul__(self, other)
object.__imatmul__(self, other)
object.__itruediv__(self, other)
object.__ifloordiv__(self, other)
object.__imod__(self, other)
object.__ipow__(self, other[, modulo])
object.__ilshift__(self, other)
object.__irshift__(self, other)¶
object.__iand__(self, other)
object.__ixor__(self, other)
object.__ior__(self, other)
```