Pythonの基本③【特殊メソッド】

## Pythonの特殊メソッドについて
Pythonでは、特殊メソッドと呼ばれる、ダブルアンダースコア（`__`）で囲まれたメソッドがあります。これらのメソッドは、通常のメソッドとは異なり、Pythonの言語機能をカスタマイズするために使用されます。特殊メソッドを適切に実装することで、オブジェクトの振る舞いや操作を定義することができます。

## 特殊メソッドとは
特殊メソッドは、Pythonの組み込み型における演算や操作をカスタマイズするために使用されます。例えば、+ 演算子や * 演算子、インデックスやスライスの取得、オブジェクトの比較など、多くの組み込み演算は特殊メソッドによってサポートされています。

特殊メソッドを定義することで、ユーザー定義のクラスを組み込み型のように振る舞わせることができます。これにより、クラスのインスタンスを自然な形で操作することが可能になります。

## よく使う特殊メソッド一覧
以下は、よく使われる特殊メソッドの一覧です。

### インスタンスの生成と破壊に関するメソッド：
`__init__(self, ...)`: インスタンスが初期化される際に呼ばれるコンストラクタメソッド。
`__new__(cls, *args, **kwargs)`: インスタンスの生成をカスタマイズするためのメソッド。
`__del__(self)`: インスタンスが破棄される際に呼ばれるメソッド。

### イテレーターオブジェクトの操作に関するメソッド：
`__len__(self)`: オブジェクトの長さを返すメソッド。
`__getitem__(self, key)`: インデックスやキーを使ってオブジェクトの要素を取得するメソッド。
`__setitem__(self, key, value)`: インデックスやキーを使ってオブジェクトの要素を設定するメソッド。
`__delitem__(self, key)`: インデックスやキーを使ってオブジェクトの要素を削除するメソッド。
`__iter__(self)`: イテレーションをサポートするためのイテレータオブジェクトを返すメソッド。
`__next__(self)`: イテレータオブジェクトの次の要素を返すメソッド。

### 算術演算子を定義するメソッド：
`__add__(self, other)`: + 演算子の振る舞いを定義するメソッド。
`__sub__(self, other)`: - 演算子の振る舞いを定義するメソッド。
`__mul__(self, other)`: * 演算子の振る舞いを定義するメソッド。
`__truediv__(self, other)`: / 演算子の振る舞いを定義するメソッド。
`__floordiv__(self, other)`: // 演算子の振る舞いを定義するメソッド。
`__mod__(self, other)`: % 演算子の振る舞いを定義するメソッド。
`__pow__(self, other[, modulo])`: ** 演算子の振る舞いを定義するメソッド。

### 比較演算子を定義するメソッド：
`__eq__(self, other)`: == 演算子の振る舞いを定義するメソッド。
`__ne__(self, other)`: != 演算子の振る舞いを定義するメソッド。
`__lt__(self, other)`: < 演算子の振る舞いを定義するメソッド。
`__le__(self, other)`: <= 演算子の振る舞いを定義するメソッド。
`__gt__(self, other)`: > 演算子の振る舞いを定義するメソッド。
`__ge__(self, other)`: >= 演算子の振る舞いを定義するメソッド。

### その他
`__repr__(self)`: オブジェクトの公式な文字列表現を返すメソッド。
`__str__(self)`: str() 関数が呼ばれた際に返される文字列表現を定義するメソッド。
`__bool__ (self)`: オブジェクトが真偽値として扱われる際の振る舞いを定義するメソッド。

## 実際の使用例
イテレーターオブジェクトの操作に関するメソッドと、生成と破壊に関するメソッド
```python
class MyList:
    def __init__(self, data):
        self.data = data

    def __len__(self):
        return len(self.data)

    def __getitem__(self, index):
        return self.data[index]

    def __setitem__(self, index, value):
        self.data[index] = value

# 使用例
my_list = MyList([1, 2, 3, 4, 5])
print(len(my_list))  # Output: 5
print(my_list[0])    # Output: 1
my_list[0] = 10
print(my_list[0])    # Output: 10
```
比較演算子や算術演算子に関するメソッド
```python
class Vector:
	def __init__(self, x, y):
		self.x = x
		self.y = y

	def __add__(self, other):
		return Vector(self.x + other.x, self.y + other.y)

	def __sub__(self, other):
		return Vector(self.x - other.x, self.y - other.y)

	def __mul__(self, scalar):
		return Vector(self.x * scalar, self.y * scalar)

	def __truediv__(self, scalar):
		return Vector(self.x / scalar, self.y / scalar)

	def __eq__(self, other):
		return self.x == other.x and self.y == other.y

	def __ne__(self, other):
		return not self == other

	def __lt__(self, other):
		return self.x ** 2 + self.y ** 2 < other.x ** 2 + other.y ** 2

	def __bool__(self):
		return self.x != 0 or self.y != 0

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

# 使用例
v1 = Vector(1, 2)
v2 = Vector(2, 3)
print(v1 + v2)  # Output: (3, 5)
print(v1 - v2)  # Output: (-1, -1)
print(v1 * 3)   # Output: (3, 6)
print(v1 / 2)   # Output: (0.5, 1.0)
print(v1 == v2) # Output: False
print(v1 != v2) # Output: True
print(v1 < v2)  # Output: True
print(bool(v1)) # Output: True
print(bool(Vector(0, 0))) # Output: False
print(str(v1))  # Output: (1, 2)
```

## まとめ
特殊メソッドを適切に実装することで、ユーザー定義のクラスを組み込み型のように振る舞わせることができます。