【要約】Python のクラスメソッド [Zenn_Python] | Summary by TechDistill
> Source: Zenn_Python
Execute Primary Source
// Problem
Pythonのクラスメソッドを、C++やJavaのような静的な仕組みと誤認することで、継承時に予期せぬ副作用に直面する問題がある。具体的には、以下の課題が挙げられる。
- ・
@classmethodのレシーバであるclsが、継承によって呼び出し元のクラスに動的に変化する。 - ・クラス変数への
+=操作が、不変オブジェクトでは代入、可変オブジェクトでは破壊的変更として振る舞う。 - ・
@staticmethodが、呼び出し方次第で動的なメソッド解決の影響を受ける。
// Approach
筆者は、他言語との比較および具体的なコード実験を通じて、Python特有の動的な挙動を解明するアプローチをとった。主な検証ステップは以下の通りである。
- ・C++のstaticメンバ関数と比較し、Pythonのレシーバ概念の差異を定義した。
- ・継承関係(
class B(A))を用いた実験により、clsが指すクラスの動的な変化を検証した。 - ・不変(
X = "A")と可変(Y = ["A"])のクラス変数に対し、+=演算子の挙動の違いを比較した。 - ・
@staticmethodを用いた、インスタンス経由のメソッド呼び出しにおける解決順序を検証した。
// Result
実験の結果、Pythonのメソッド解決がMROに基づいた動的なプロセスであることが実証された。これにより、以下の知見が得られた。
- ・
@classmethodにおけるclsは、必ずしも定義時のクラスを指さない。 - ・クラス変数の更新は、オブジェクトの型(mutable/immutable)により、参照先や挙動が大きく異なる。
- ・
@staticmethodは、C++の静的関数とは異なり、動的な解決の性質を保持している。
Senior Engineer Insight
> Pythonの動的なメソッド解決は柔軟だが、大規模システムでは「予測不可能性」という致命的なリスクとなる。特に、継承を利用したクラス変数の操作は、MROとオブジェクトの可変性が組み合わさることで、極めて難解な副作用を生む。実戦では、クラス変数に状態を持たせる設計を避け、状態管理はインスタンスや外部のコンポーネントに委ねるべきだ。また、
@staticmethodを「完全な静的関数」と過信せず、継承の影響を考慮した設計が求められる。