web-dev-qa-db-ja.com

python-静的メソッドまたはトップレベル関数を使用する必要があります

私はJavaバックグラウンドから来ており、Pythonは初めてです。ファイルの読み取りと書き込みに関連するアプリケーションに固有のいくつかのヘルパー関数を共有するいくつかのスクリプトがあります。読み取りに関連するいくつかの関数、正しいアプローチを探しているときに、私はこれを見ました: Pythonの静的メソッド?

彼は彼の答えで言及しています:

最後に、staticmethodは慎重に使用してください。 Pythonで静的メソッドが必要となる状況は非常に少なく、個別の「トップレベル」関数がより明確である場合に、それらが何度も使用されるのを見てきました。

私はトップレベルの関数をよく理解していませんし、この単純な例の方が良いとは思いません。1)静的リーダー関数を持つリーダー用のクラスを作成し、ライター用に同じクラスを作成するか、2)これらのヘルパーを宣言しますグローバル機能として、なぜですか?

編集:[〜#〜]本当に[〜#〜]この件についての良い記事私が見つけたばかり http://tomayko.com/writings/the-static-method-thing

39
Brad

Javaでは、クラスをどこでも使用する(間違った)アイデアがあります。状態を共有しない静的関数をグループ化するだけです(したがって、そのようなクラスはインスタンス化されません)。

ここのPythonは異なることを求めています。いくつかの共有状態を持たない関数がある場合1 (したがってJavaは通常static関数になります)で、「実際の」クラス(=実際にインスタンス化されるクラス)とは密接に関連していないため、無料の関数を使用するだけですモジュール内。

この背後にある理由は、クラスを実際にインスタンス化する場合にのみクラスが必要であるため、インスタンス固有の状態を共有する必要のないいくつかの関数のコンテナーとしてクラスを使用しても意味がないためです。

実際、somewhatモジュールをstaticクラスと考えることができます。つまり、関数(=静的メソッド)、モジュール変数(=静的フィールド)および型のコンテナーです。

Python=のいいところは、トップレベルの関数を使用しても、グローバルな名前空間汚染の問題が発生しないことです。これは、Pythonトップレベルの関数/オブジェクト/にあるためです。 ..は引き続きモジュールスコープなので、不要なclass- taxなしで、モジュールごとに関数をグループ化できます。


  1. 実際、それらはcanがモジュールレベルの変数(つまり、シングルトン)の形式で、いくつかの共有状態を持っています。再び、アナロジーmodule-staticクラスが保持されているようです。
46
Matteo Italia

Python(import this):

Namespaces are one honking great idea -- let's do more of those!

Javaのような言語で静的メソッドを作成する主な理由の1つは、これらのメソッドがグローバル名前空間を汚染しないようにすることです(Java =「パッケージレベル」の関数を完全に禁止することにより、独自の名前空間規則を適用します!)Pythonでは、すべての「トップレベル」関数はそれらの関数を含むモジュールの名前空間内に自動的に配置されるため、このグローバル名前空間を汚染する危険はありません。仕方。

つまり、他の多くの言語と同様に、Pythonはいくつかの方法で名前空間を作成できます。この場合、モジュールが同じものを提供する場合、静的メソッドのみを含むクラスを作成する必要はほとんどありません。クラスの定義に関連する混乱(または認知的負荷)のない名前空間の目的。

13
lmjohns3

名前空間の汚染の問題です。複数のクラスと、特定のクラスとその子孫に対してのみ意味のあるいくつかの関数を持つモジュールがある場合は、それを静的メソッドにします。静的メソッドは、クラス名またはクラスのオブジェクトを使用して呼び出すことができます。

>>> class A(object):
...     @staticmethod
...     def static_1():
...             print 'i am static'
...     def a(self):
...             self.static_1()
...
>>> A.static_1()
i am static
>>> a=A()
>>> a.a()
i am static
>>> a.static_1()
i am static
>>> class B(A):
...     pass
...
>>> b=B()
>>> b.static_1()
i am static
>>>
5
tdelaney

関数がクラスに関連している場合は、それを静的メソッドにします。例えば:

class DBobject():
    name = StringProperty()

    @staticmethod
    def get_by_name(name):
        return db.select('select * from DBobject where name = "%s"' % name)

python = DBobject.get_by_name('python')

つまり、メソッドはDBobjectクラスに完全に関連しているため、静的メソッドである必要があります。

4
Brent Washburne

Python静的メソッドのもう1つの側面は、インスタンスで呼び出された場合、selfのインスタンスがなくても、呼び出された変数の型で多態的であるということです。

例えば:

class BaseClass:
    @staticmethod
    def my_method():
        return 0


class SubclassLeft:
    @staticmethod
    def my_method():
        return "left"


class SubclassRight:
    @staticmethod
    def my_method():
        return "right"


instances = [BaseClass(), SubclassLeft(), SubclassRight()]

for i in instances:
    print(i.my_method())

これを実行すると

$ python example.py
0
left
right
0
andyg0808