🔰 Python初心者が学ぶ「特殊メソッド」とは？ 〜 __str__ / __repr__ の違いと使い分け〜（自分用）

✅ はじめに
--
Pythonのクラスを学んでいると、ときどき__ __init__ __、 __ __str__ __ 、 __ __repr__ __ のように 両端にアンダースコアが2つずつついたメソッド を見かけることがあります。
```python:example.py
def __init__(self, name): ...
```
これらは 「特殊メソッド」（または 「マジックメソッド」）と呼ばれ、Pythonのオブジェクトに特別な振る舞いを与えるための仕組みです。

🔍 特殊メソッドって何？
--
特殊メソッドとは、Pythonが特定のタイミングで自動的に呼び出す、予約されたメソッド名のことです。

| 特殊メソッド名    | 役割           | 呼び出し例                |
| ---------- | ------------ | -------------------- |
| `__init__` | コンストラクタ（初期化） | `obj = MyClass()`    |
| `__str__`  | 文字列化（ユーザー向け） | `print(obj)`         |
| `__repr__` | 文字列表現（開発者向け） | `repr(obj)`、REPLでの表示 |
| `__len__`  | 長さの取得        | `len(obj)`           |
| `__eq__`   | 等価比較（==）の定義  | `obj1 == obj2`       |
| `__add__`  | 足し算（+）の動作定義  | `obj1 + obj2`        |

🔄 特殊メソッドを使わなかったらどうなる？
--
ではもし __str__ や __repr__ といった特殊メソッドを一切使わなかったら、print(obj) のような表示はどうなるのでしょうか？

🔸 例：特殊メソッドを使わないクラス定義
```python:example.py
# example.py
class Person:
    def __init__(self, name):
        self.name = name

    def check_name(self):
        return f"私の名前は{self.name}です"
```
この Person クラスには、check_name() という名前を返す独自メソッドがありますが、__str__ や __repr__ は定義されていません。

▶ 使用例と出力結果
```python:example.py
person = Person("田中")

print(person)
# 出力例:
# <__main__.Person object at 0x0000019A701F3B50>

print(person.check_name())
# 出力:
# 私の名前は田中です
```
📌 解説
print(person) を実行すると、オブジェクトのメモリアドレスを含んだ情報（<__main__.Person object at ...>）が表示されます。
これは __str__ や __repr__ を定義していないため、Pythonがデフォルトのオブジェクト表現を使っているからです。

一方、person.check_name() を使えば、自分で定義した出力が得られます。
しかしこれは 開発者が毎回明示的にメソッドを呼び出す必要がある ため、手間がかかります。

🧪 今回の主役：__ __str__ __ と __repr__を使えばこうなる！
-
👀 __str__ の役割：人に見せる「説明文」
print(obj) などで呼ばれる
人間が読んで理解しやすい文字列を返す

🔧 __repr__ の役割：開発者が見る「再現可能な表現」
repr(obj)、あるいは Python の対話モードで obj と打つと呼ばれる
「その文字列を eval() したら同じオブジェクトが再生成できる」ような表現が理想
```python:example.py
class Person:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return f"{self.name}さんです"

    def __repr__(self):
        return f"{type(self).__name__}(name={self.name!r})"
```
▶ 使用例：
```python:example.py
p = Person("田中")

print(p)         # → 田中さんです (__str__)
print(str(p))    # → 田中さんです (__str__)
print(repr(p))   # → Person(name='田中') (__repr__)
print([p])       # → [Person(name='田中')] (__repr__ がリスト表示などに使われる)
```
👨‍🏫 補足：どちらか片方だけ定義してもOK？
--
どちらか一方だけでも動作しますが、以下のような挙動になります。
__str__ が定義されていない場合 → __repr__ が print(obj) にも使われます
__repr__ も未定義の場合 → <__main__.Person object at 0x...> のようなデフォルトの表示になります

✅ 結論：__str__ と __repr__ は両方書くのがベスト！
--
| メソッド       | 説明            | 目的             |
| ---------- | ------------- | -------------- |
| `__str__`  | ユーザー向けにわかりやすい | `print()`などで表示 |
| `__repr__` | 開発者向けに詳しい表示   | ログ・デバッグなど      |

特にライブラリを作るときや、ログ出力が重要なアプリケーションでは、__repr__ をきちんと書いておくと、後々のデバッグ効率が大きく変わる。

📌 まとめ
--
特殊メソッドは Python が内部的に呼び出す「特別なメソッド」

<strong>__ __str__ __ は人間にとってのわかりやすさ
__ __repr__ __は開発者にとってのデバッグしやすさ</strong>

📚 関連リンク
--
<a href="https://docs.python.org/ja/3/reference/datamodel.html">Python公式ドキュメント – データモデル（特殊メソッド）</a>
<a href="https://docs.python.org/ja/3/reference/datamodel.html#object.__str__">Python公式ドキュメント –__ __str__ __ </a>
<a href="https://docs.python.org/ja/3/reference/datamodel.html#object.__repr__">Python公式ドキュメント –__ __repr__ __ </a>