私は、Pythonのオンとオフをいじくり回しているJava開発者です。私は最近、JavaプログラマーがPythonを手にしたときによくある間違いについて言及しているこの記事に出くわしました。最初のものが私の目に留まりました:
Javaの静的メソッドは、Pythonクラスメソッドに変換されません。確かに、ほぼ同じ効果が得られますが、クラスメソッドの目標は、実際にはJavaでは通常は不可能なこと(デフォルト以外のコンストラクターを継承するなど)を実行することです。Java静的メソッドの慣用的な変換は通常、クラスメソッドや静的メソッドではなく、モジュールレベルの関数です。(静的なfinalフィールドは、モジュールレベルの定数に変換する必要があります。)
これはパフォーマンスの問題ではありませんが、このようなJavaイディオムコードを使用する必要があるPythonプログラマーは、Foo.someFunctionである必要があるときにFoo.Foo.someMethodと入力するとかなりイライラします。ただし、classmethodの呼び出しには、staticmethodまたは関数の呼び出しには含まれない追加のメモリ割り当てが含まれることに注意してください。
ああ、そしてそれらすべてのFoo.Bar.Baz属性チェーンも無料ではありません。Javaでは、これらの点線の名前はコンパイラーによって検索されるため、実行時に、それらの名前がいくつあるかは実際には関係ありません。Pythonでは、ルックアップは実行時に行われるため、各ドットがカウントされます。(Pythonでは、「フラットはネストよりも優れている」ことを覚えておいてください。ただし、パフォーマンスよりも「読みやすさのカウント」と「シンプルは複雑よりも優れています」に関連しています。)
staticmethodのドキュメントには次のように書かれているので、これは少し奇妙だと思いました。
Pythonの静的メソッドは、JavaまたはC++で見られるものと似ています。代替クラスコンストラクターの作成に役立つバリアントについては、classmethod()も参照してください。
さらに不可解なのは、このコードです。
class A:
def foo(x):
print(x)
A.foo(5)
Python 2.7.3では期待どおりに失敗しますが、3.2.3では正常に機能します(ただし、Aのインスタンスでメソッドを呼び出すことはできず、クラスでのみ呼び出すことができます)。
したがって、静的メソッドを実装する方法は3つあり(classmethodを使用してカウントする場合は4つ)、それぞれ微妙な違いがあり、そのうちの1つは文書化されていないようです。これは、Pythonのマントラである「1つ、できれば1つだけ」の明白な方法とは相容れないようです。最もPythonicなイディオムはどれですか?それぞれの長所と短所は何ですか?
これまで私が理解していることは次のとおりです。
モジュール機能:
- Foo.Foo.f()の問題を回避します
- モジュールの名前空間を他の方法よりも汚染します
- 継承なし
staticmethod:
- クラスに関連する関数をクラス内およびモジュール名前空間外に保持します。
- クラスのインスタンスで関数を呼び出すことができます。
- サブクラスはメソッドをオーバーライドできます。
classmethod:
- staticmethodと同じですが、最初の引数としてクラスを渡します。
通常の方法(Python 3のみ):
- staticmethodと同じですが、クラスのインスタンスでメソッドを呼び出すことはできません。
私はこれを考えすぎていますか?これは問題ではありませんか?助けてください!