Python の静的メソッドは、Python 2.2 でのいわゆる「新しいスタイルのクラス」の導入にさかのぼります。これ以前は、クラスのメソッドは、クラスの属性として格納された単なる普通の関数でした:
class OldStyleClass:
def method(self):
print "'self' is just the first argument of this function"
instance = OldStyleClass()
OldStyleClass.method(instance) # Just an ordinary function call
print repr(OldStyleClass.method) # "unbound method..."
インスタンスのメソッド呼び出しは、インスタンスを関数の最初の引数に自動的にバインドするために特別に処理されました。
instance.method() # 'instance' is automatically passed in as the first parameter
print repr(instance.method) # "bound method..."
Python 2.2 では、クラス システムの多くが再考され、「新しいスタイルのクラス」、つまり を継承するクラスとして再設計されましたobject
。新しいスタイルのクラスの機能の 1 つは「記述子」でした。これは基本的に、クラスの属性の記述、取得、および設定を担当するクラス内のオブジェクトです。記述子には__get__
、クラスとインスタンスを渡すメソッドがあり、クラスまたはインスタンスの要求された属性を返す必要があります。
記述子により、単一の API を使用して、プロパティ、クラス メソッド、静的メソッドなどのクラス属性の複雑な動作を実装できるようになりました。たとえば、staticmethod
記述子は次のように実装できます。
class staticmethod(object):
"""Create a static method from a function."""
def __init__(self, func):
self.func = func
def __get__(self, instance, cls=None):
return self.func
これを、classes 属性のすべての単純な関数に対してデフォルトで使用される、通常のメソッドの架空の pure-python 記述子と比較してください (これは、インスタンスからのメソッド検索で正確に起こることではありませんが、自動の「自己」を処理します)。口論):
class method(object):
"""Create a method from a function--it will get the instance
passed in as its first argument."""
def __init__(self, func):
self.func = func
def __get__(self, instance, cls=None):
# Create a wrapper function that passes the instance as first argument
# to the original function
def boundmethod(*args, **kwargs):
return self.func(self, *args, **kwargs)
return boundmethod
したがって、 を記述するときmethod = staticmethod(method)
は、実際には、元の関数を変更せずに返すことを仕事とする新しい記述子を作成し、この記述子をクラスの「メソッド」属性に格納しています。
元の機能を元に戻すだけでも大変な作業のように思われる場合は、その通りです。ただし、通常のメソッド呼び出しがデフォルトのケースであるため、静的メソッドとクラス メソッドは個別に実装する必要があり、記述子を使用すると、1 つの単純な API でこれらおよびその他の複雑な動作を有効にすることができます。
他の人がすでに指摘しているように、Python 2.4 で導入されたデコレーター構文は、静的メソッドを宣言するためのより便利な方法を提供しますが、これは単なる構文上の利便性であり、静的メソッドの動作方法を変更するものではありません。
新しいスタイルの詳細については、http: //www.python.org/doc/2.2.3/whatsnew/sect-rellinks.htmlおよびhttp://users.rcn.com/python/download/Descriptor.htmを参照してください。クラスと記述子。