次のように、クラスを初期化せずにそれらを呼び出すことができるように、Pythonに静的メソッドを含めることは可能ですか。
ClassName.StaticMethod ( )
うん、 staticメソッド デコレータを使う
class MyClass(object):
@staticmethod
def the_static_method(x):
print x
MyClass.the_static_method(2) # outputs 2
一部のコードでは、デコレータではなく関数としてstaticmethod
を使用して、静的メソッドを定義する古い方法を使用することがあります。これは古いバージョンのPython(2.2と2.3)をサポートしなければならない場合にのみ使われるべきです。
class MyClass(object):
def the_static_method(x):
print x
the_static_method = staticmethod(the_static_method)
MyClass.the_static_method(2) # outputs 2
これは最初の例(@staticmethod
を使用)とまったく同じですが、Niceデコレータ構文を使用していません。
最後に、 staticmethod()
を控えめに使用してください。 Pythonで静的メソッドが必要な状況はごくわずかですが、私はそれらが別々の「トップレベル」関数がより明確になるであろう場所で何度も使用されるのを見ました。
静的メソッドは、暗黙の最初の引数を受け取りません。静的メソッドを宣言するには、次の慣用句を使用します。
class C: @staticmethod def f(arg1, arg2, ...): ...
@staticmethod形式は関数です。 デコレータ - 詳細は 関数定義 の関数定義の説明を参照してください。
クラス(
C.f()
など)またはインスタンス(C().f()
など)のどちらでも呼び出すことができます。インスタンスはそのクラス以外は無視されます。Pythonの静的メソッドは、JavaまたはC++のものと似ています。より高度な概念については、
classmethod()
を参照してください。静的メソッドの詳細については、 標準型階層 にある標準型階層に関するドキュメントを参照してください。
バージョン2.2の新機能.
バージョン2.4で変更された仕様:関数デコレータ構文が追加されました.
Stevenは実際に正しいと思います 。元の質問に答えるには、クラスメソッドを設定するために、最初の引数が呼び出し元のインスタンスにならないと仮定して、クラスからメソッドを呼び出すだけであることを確認します。
(この答えはPython 3.xを参照していることに注意してください。Python2.xでは、クラス自体のメソッドを呼び出すためのTypeError
が得られます。)
例えば:
class Dog:
count = 0 # this is a class variable
dogs = [] # this is a class variable
def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.count += 1
Dog.dogs.append(name)
def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))
def rollCall(n): #this is implicitly a class method (see comments below)
print("There are {} dogs.".format(Dog.count))
if n >= len(Dog.dogs) or n < 0:
print("They are:")
for dog in Dog.dogs:
print(" {}".format(dog))
else:
print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
このコードでは、 "rollCall"メソッドは最初の引数がインスタンスではないと想定しています(クラスではなくインスタンスによって呼び出された場合のように)。 "rollCall"がインスタンスではなくクラスから呼び出される限り、コードは正常に機能します。インスタンスから "rollCall"を呼び出そうとすると、次のようになります。
rex.rollCall(-1)
ただし、自身と-1の2つの引数を送信するため、例外が発生します。 "rollCall"は1つの引数のみを受け入れるように定義されています。
ちなみに、rex.rollCall()は正しい数の引数を送信しますが、関数がnが数値であることを期待している場合はnがDogインスタンス(つまりrex)を表すため、例外も発生します。
これが装飾の出番です: "rollCall"メソッドの前に
@staticmethod
それから、メソッドが静的であることを明示的に述べることによって、インスタンスから呼び出すことさえできます。今、
rex.rollCall(-1)
うまくいくでしょう。メソッド定義の前に@staticmethodを挿入すると、インスタンスが自分自身を引数として送信するのを停止します。
@staticmethod行をコメントアウトして、またはコメントアウトせずに次のコードを試すことでこれを確認できます。
class Dog:
count = 0 # this is a class variable
dogs = [] # this is a class variable
def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.count += 1
Dog.dogs.append(name)
def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))
@staticmethod
def rollCall(n):
print("There are {} dogs.".format(Dog.count))
if n >= len(Dog.dogs) or n < 0:
print("They are:")
for dog in Dog.dogs:
print(" {}".format(dog))
else:
print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
rex.rollCall(-1)
はい、 staticmethod デコレータをチェックしてください。
>>> class C:
... @staticmethod
... def hello():
... print "Hello World"
...
>>> C.hello()
Hello World
あなたは本当に@staticmethod
デコレータを使う必要はありません。メソッドを宣言するだけで(selfパラメータは必要ありません)、それをクラスから呼び出すだけです。デコレータは、インスタンスからもそれを呼び出せるようにしたい場合にのみ存在します(これはあなたがやりたいことではありませんでした)。
ほとんどの場合、あなたはただ関数を使用します...
Pythonの静的メソッド?
次のように、クラスを初期化せずにそれらを呼び出すことができるように、Pythonに静的メソッドを含めることは可能ですか。
ClassName.StaticMethod()
はい、静的メソッドをこのように作成することができます(ただし、メソッドにCamelCaseの代わりにアンダースコアを使用するのはもう少し Pythonic です)。
class ClassName(object):
@staticmethod
def static_method(kwarg1=None):
'''return a value that is a function of kwarg1'''
上記はデコレータ構文を使用しています。この構文は以下と同等です。
class ClassName(object):
def static_method(kwarg1=None):
'''return a value that is a function of kwarg1'''
static_method = staticmethod(static_method)
これはあなたが説明したように使うことができます。
ClassName.static_method()
静的メソッドの組み込みの例は、Python 3のstr.maketrans()
です。これは、Python 2のstring
モジュールの関数です。
あなたが説明するのに使うことができるもう一つのオプションはclassmethod
です、違いはclassmethodが暗黙の最初の引数としてクラスを取得し、そしてサブクラス化されるならそれが暗黙の最初の引数としてサブクラスを取得することです。
class ClassName(object):
@classmethod
def class_method(cls, kwarg1=None):
'''return a value that is a function of the class and kwarg1'''
cls
は最初の引数に必須の名前ではありませんが、他のものを使用すると、経験豊富なPythonコーダーの大部分はそれを不適切と見なします。
これらは通常、代替コンストラクタとして使用されます。
new_instance = ClassName.class_method()
組み込みの例はdict.fromkeys()
です。
new_dict = dict.fromkeys(['key1', 'key2'])
おそらく最も簡単なオプションは、これらの関数をクラスの外に置くことです。
class Dog(object):
def __init__(self, name):
self.name = name
def bark(self):
if self.name == "Doggy":
return barking_sound()
else:
return "yip yip"
def barking_sound():
return "woof woof"
このメソッドを使用すると、内部オブジェクトの状態を変更または使用する(副作用がある)関数をクラス内に保持し、再利用可能なユーティリティ関数を外部に移動できます。
このファイルをdogs.py
と呼びましょう。これらを使用するには、dogs.Dog.barking_sound
ではなくdogs.barking_sound()
を呼び出します。
あなたが本当に静的メソッドがクラスの一部であることを本当に必要とするなら、あなたは staticmethod デコレータを使うことができます。
静的メソッドオブジェクト の振る舞いの特殊性は別として、モジュールレベルのコードをまとめることに関しては、ある種の美しさがあります。
# garden.py
def trim(a):
pass
def strip(a):
pass
def bunch(a, b):
pass
def _foo(foo):
pass
class powertools(object):
"""
Provides much regarded gardening power tools.
"""
@staticmethod
def answer_to_the_ultimate_question_of_life_the_universe_and_everything():
return 42
@staticmethod
def random():
return 13
@staticmethod
def promise():
return True
def _bar(baz, quux):
pass
class _Dice(object):
pass
class _6d(_Dice):
pass
class _12d(_Dice):
pass
class _Smarter:
pass
class _MagicalPonies:
pass
class _Samurai:
pass
class Foo(_6d, _Samurai):
pass
class Bar(_12d, _Smarter, _MagicalPonies):
pass
...
# tests.py
import unittest
import garden
class GardenTests(unittest.TestCase):
pass
class PowertoolsTests(unittest.TestCase):
pass
class FooTests(unittest.TestCase):
pass
class BarTests(unittest.TestCase):
pass
...
# interactive.py
from garden import trim, bunch, Foo
f = trim(Foo())
bunch(f, Foo())
...
# my_garden.py
import garden
from garden import powertools
class _Cowboy(garden._Samurai):
def hit():
return powertools.promise() and powertools.random() or 0
class Foo(_Cowboy, garden.Foo):
pass
特定のコンポーネントを使用することを意図したコンテキストでは、より直感的で自己文書化され、純粋なテストケースでテストモジュールを実際のモジュールにマッピングする方法について簡単なアプローチをとることができます。 。
このアプローチをプロジェクトのユーティリティコードの編成に適用することが実行可能であることがよくあります。多くの場合、人々はすぐにutils
パッケージを急いで作成し、最終的に9個のモジュールで120個のLOCを持ち、残りはせいぜい2ダースのLOCです。私はこれから始めてそれをパッケージに変換し、本当にそれらに値する獣のためだけにモジュールを作成することを好みます:
# utils.py
class socket(object):
@staticmethod
def check_if_port_available(port):
pass
@staticmethod
def get_free_port(port)
pass
class image(object):
@staticmethod
def to_rgb(image):
pass
@staticmethod
def to_cmyk(image):
pass
そのため、静的メソッドはクラスのオブジェクトを作成せずに呼び出すことができるメソッドです。例えば :-
@staticmethod
def add(a, b):
return a + b
b = A.add(12,12)
print b
上記の例では、メソッドadd
はオブジェクト名ではなくクラス名A
によって呼び出されます。