概要(strは「人に見せる文字列表現」を返す特別メソッド)
strは、オブジェクトをprintしたり、str()に渡したときの“人向けの文字列表現”を定義します。これを実装しておくと、ログやUI、コンソール表示が一気に読みやすくなります。初心者がまず押さえるべきは、strの役割、reprとの違い、フォーマットのコツ、そしてデバッグ・ロギングで迷わない設計です。
基本の使い方(printやstr()で呼ばれる仕組み)
最小例と動作の確認
class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
def __str__(self) -> str:
return f"{self.name}({self.age}歳)"
p = Person("太郎", 23)
print(p) # 太郎(23歳) ← __str__が使われる
print(str(p)) # 同じく__str__が使われる
Python「人に見せたい形」を素直に作るのが基本です。f文字列を使うと簡潔に書けます。
reprとの違い(役割の線引き)
class Person:
def __init__(self, name: str, age: int):
self.name = name; self.age = age
def __str__(self) -> str: # 人向け(UI/ログの短い表現)
return f"{self.name}({self.age}歳)"
def __repr__(self) -> str: # 開発者向け(再現可能性を意識)
return f"Person(name={self.name!r}, age={self.age!r})"
PythonUIやログの一行表示はstr、デバッグやREPLでの詳細はrepr。両方実装しておくと場面で使い分けできます。
設計のコツ(安定した表示・個人情報の扱い・長さ管理)
表示は「短く・安定・情報量は適度に」
ログやUIでは、行が長すぎると読みにくくなります。要点(主要属性)を短くまとめ、可変長データは件数やサマリにします。
class Order:
def __init__(self, order_id: str, items: list[tuple[str, int]]):
self.order_id = order_id
self.items = items
def __str__(self) -> str:
count = len(self.items)
return f"Order#{self.order_id} items={count}"
Python機微情報はマスクする
APIキーやトークン、メールなどは“そのまま出さない”のが安全設計です。strは人目に触れる機会が多いので、必ずマスクしましょう。
class ApiKey:
def __init__(self, token: str):
self.token = token
def __str__(self) -> str:
t = self.token
return t[:4] + "..." + t[-4:] if len(t) > 8 else "***"
Pythonエラー時も壊れない表示
欠損値やNoneが来ても例外にせず、デフォルト表現を返すとログ出力中の失敗を防げます。
class User:
def __init__(self, name: str | None, id_: str | None):
self.name = name or "unknown"
self.id_ = id_ or "-"
def __str__(self) -> str:
return f"User[{self.id_}] {self.name}"
Python実務例(Web/APIのモデル・クライアント・例外で活かす)
モデルの見やすい一行サマリ
APIレスポンスを整えたモデルは、strで俯瞰できるようにしておくと、ログ・デバッグ効率が上がります。
class UserModel:
def __init__(self, data: dict):
self.user_id = str(data.get("id", ""))
self.name = data.get("name") or "unknown"
self.role = data.get("role") or "user"
def __str__(self) -> str:
return f"User({self.user_id}, {self.name}, role={self.role})"
Pythonクライアントの接続概要を短く
接続先とタイムアウトなど、運用で重要な設定を一目でわかる形にします。
import requests
class ApiClient:
def __init__(self, base_url: str, api_key: str, timeout: float = 5.0):
self.base_url = base_url
self.timeout = timeout
self.session = requests.Session()
self.session.headers.update({"Authorization": f"Bearer {api_key}"})
def __str__(self) -> str:
return f"ApiClient({self.base_url}, timeout={self.timeout})"
Python例外型の文字列表現で文脈を伝える
ドメイン例外のstrに簡潔な説明と主要IDを含め、ログで原因追跡しやすくします。
class ServiceError(Exception):
def __init__(self, message: str, uid: str | None = None):
super().__init__(message)
self.uid = uid
def __str__(self) -> str:
return f"{self.args[0]} (uid={self.uid or '-'})"
Python深掘り(strを使う場面、フォールバック、テストの観点)
どこで使われるか(暗黙の呼び出し)
- print(obj)、format文字列(f”{obj}”)、loggingでの%や{}フォーマットなど、表示系で暗黙にstrが呼ばれます。
- デバッグシェル(REPL)は通常reprを使う点に注意。必要ならreprも実装しましょう。
reprへのフォールバック
strが未実装のとき、str(obj)はreprの結果を使います。最初はreprだけ用意するのも現実的です。両方をセットで整えるのが理想。
テストの書き方(安定性の検証)
- 期待する文字列を固定化し、主要属性の更新で表示が正しく変わること、欠損時に安全な代替表現になることをアサートします。
- 機微情報がマスクされていることを必ずテストします。
例題(注文ドメインの表示を整えて運用しやすくする)
注文・ユーザー・クライアントの表示を統一する
class Order:
def __init__(self, order_id: str, items: list[tuple[str, int]]):
self.order_id = order_id
self.items = items
self.status = "init"
def __str__(self) -> str:
return f"Order#{self.order_id} status={self.status} items={len(self.items)}"
class UserModel:
def __init__(self, uid: str, name: str | None = None):
self.uid = uid
self.name = name or "unknown"
def __str__(self) -> str:
return f"User({self.uid}, {self.name})"
import requests
class Client:
def __init__(self, base_url: str, key: str, timeout: float = 5.0):
self.base_url = base_url
self.timeout = timeout
self.session = requests.Session()
self.session.headers.update({"Authorization": f"Bearer {key}"})
def __str__(self) -> str:
return f"Client({self.base_url}, timeout={self.timeout})"
Pythonこのように、主要なクラスのstrを揃えておくと、ログに出たときに全体像がすぐ掴めます。
まとめ(strは“人に伝わる一行”を作るための出口)
strは、人間に読ませるための文字列表現を返す特別メソッドです。UI・ログ・メッセージでのわかりやすさが大幅に向上します。reprとの役割分担を守り、短く・安定・機微情報はマスクし、欠損でも落ちない表現を心がける。主要クラスに一貫したstrを用意するだけで、デバッグ速度と運用の安心感が段違いになります。
