回答:
はい、staticmethodデコレータを使用します
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
)。
最後に、staticmethod()
控えめに使用してください!Pythonで静的メソッドが必要となる状況は非常に少なく、個別の「トップレベル」関数がより明確である場合に、それらが何度も使用されるのを見てきました。
静的メソッドは暗黙の最初の引数を受け取りません。静的メソッドを宣言するには、次のイディオムを使用します。
class C: @staticmethod def f(arg1, arg2, ...): ...
@staticmethodフォームは関数デコレーターです。詳細については、関数定義の関数定義の説明を参照してください。
クラス(など
C.f()
)またはインスタンス(など)で呼び出すことができますC().f()
。クラス以外のインスタンスは無視されます。Pythonの静的メソッドは、JavaまたはC ++にあるものと似ています。より高度な概念については、を参照してください
classmethod()
。静的メソッドの詳細については、内標準型の階層上の文書相談の標準型の階層を。
バージョン2.2の新機能。
バージョン2.4で変更:関数デコレータ構文が追加されました。
ClassName.methodName()
、静的メソッドであるかのように、メソッドをとして呼び出すことができ、メソッドには何self
も提供されません。あなたが言ったように、まだとしても、このメソッドを呼び出すことが可能になりClassInstance.methodName()
、そしてself
関係なく、その名前の、最初のパラメータとして提供されます。
私はスティーブンが実際に正しいと思います。元の質問に答えるには、クラスメソッドを設定するために、最初の引数が呼び出し元のインスタンスではないと想定し、クラスからのみメソッドを呼び出すようにします。
(この回答は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)
ただし、2つの引数(それ自体と-1)を送信するため、例外が発生し、「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)
TypeError: unbound method rollCall() must be called with Dog instance as first argument (got int instance instead)
T.my_static_method()
or を使用しますtype(my_t_instance).my_static_method()
。
はい、staticmethodデコレーターを確認します。
>>> class C:
... @staticmethod
... def hello():
... print "Hello World"
...
>>> C.hello()
Hello World
あなたは本当に使用する必要はありません @staticmethod
デコレータ。メソッド(selfパラメータを必要としないもの)を宣言し、クラスから呼び出すだけです。デコレータは、インスタンスからも呼び出すことができるようにする場合にのみ存在します(これは望んでいたことではありませんでした)。
ほとんどの場合、関数を使用しますが...
class Dummy: def static1(): print "hello from static1" @staticmethod def static2(): print "hello from static2" Dummy.static2() Dummy.static1()
出力:hello from static2 Traceback <most last call last>:File "ll.py"、line 46、in <module> Dummy.static1()TypeError:unbound method static1()must be最初の引数としてダミーインスタンスを使用して呼び出された(代わりに何も入力されなかった)
self
、指定しない限り、最初の引数として渡します。(参照:デコレータ)
self
、呼び出し方法に応じて適切にref を挿入します。テストケース:pastebin.com/12DDV7DB。
staticmethod
デコレータは、1つのクラスとインスタンス(インスタンス上の関数を呼び出すときに、この解決策が失敗した)の両方で機能を呼び出すことができます。
class C: def callme(): print('called'); C.callme()
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()
静的メソッドの組み込み例はstr.maketrans()
Python 3にあり、これはstring
Python 2のモジュールの関数でした。
説明するように使用できる別のオプション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'])
静的メソッドオブジェクトの動作の特殊性は別として、モジュールレベルのコードの編成に関しては、それらに打ち勝つことができるある種の美しさがあります。
# 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つのモジュールで終わります。そのうちの1つは120 LOCで、残りは最高で20の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
おそらく最も簡単なオプションは、これらの関数をクラスの外に置くことです:
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.barking_sound()
ではなくを呼び出しますdogs.Dog.barking_sound
。
あなたが本当にクラスの一部であることを静的メソッドが必要な場合は、使用することができstaticmethodのデコレータを。
Python Staticメソッドは2つの方法で作成できます。
staticmethod()の使用
class Arithmetic:
def add(x, y):
return x + y
# create add static method
Arithmetic.add = staticmethod(Arithmetic.add)
print('Result:', Arithmetic.add(15, 10))
出力:
結果:25
@staticmethodの使用
class Arithmetic:
# create add static method
@staticmethod
def add(x, y):
return x + y
print('Result:', Arithmetic.add(15, 10))
出力:
結果:25
私は時々この質問に遭遇します。私が気に入っているユースケースと例は次のとおりです。
jeffs@jeffs-desktop:/home/jeffs $ python36
Python 3.6.1 (default, Sep 7 2017, 16:36:03)
[GCC 6.3.0 20170406] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cmath
>>> print(cmath.sqrt(-4))
2j
>>>
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>>
cmathオブジェクトには状態がないため、クラスcmathのオブジェクトを作成しても意味がありません。ただし、cmathは何らかの方法で関連しているメソッドのコレクションです。上記の私の例では、cmathのすべての関数が何らかの方法で複素数に作用します。
@staticmethod
最初のself
パラメーターを単に回避できるのに、なぜ装飾を追加するか、関数ポインターを使用するのですか?まあ、オブジェクトの場合a
、a.your_static_method()
他の言語では許可されているを呼び出すことはできませんが、とにかくそれは悪い習慣と見なされ、コンパイラは常にそれについて警告します