質問
次のように、クラスを初期化せずに呼び出すことができるように、Python で静的メソッドを持つことは可能ですか。
ClassName.StaticMethod ( )
解決
うん、 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
を使用して)第1の実施例と全く同じです
最後に、使用 staticmethod()
を控えめに!そこ静的メソッドはPythonで必要な非常に少ない状況があり、私は彼らが別の「トップレベル」の機能が明確にされているだろう、何度も使用さ見てきました。
静的メソッドは、暗黙的な最初の引数を受け取りません。静的メソッドを宣言するには、このイディオムを使用します:
class C: @staticmethod def f(arg1, arg2, ...): ...
@staticmethodフォームが関数である デコレータのに - <のhref = "https://docs.python.org/2/reference/compound_stmts.html#function" のrel = "noreferrer" タイトルに関数定義の説明を参照してください= "関数の定義"> の関数定義の詳細については、こちらます。
これは、(例えば
C.f()
として)(例えばC().f()
など)クラスまたはインスタンスのいずれかで呼び出すことができます。インスタンスは、そのクラスを除いて無視されます。Pythonでの静的メソッドは、JavaやC ++に見られるものと同様です。より高度な概念については、
classmethod()
を参照してください。静的メソッドの詳細については、<のhref =「https://docs.python.org/2/reference/datamodel.html#types」のrel =「noreferrer」のタイトルで、標準型の階層にドキュメントを参照してください= "種類"> の標準型の階層のを。
新バージョン2.2でます。
バージョン2.4で変更:関数デコレータ構文が追加
。
他のヒント
私はスティーブンは、実際に右のだと思います。元の質問に答えるために、そして、クラスのメソッドを設定するためには、単に最初の引数は呼び出しインスタンスで、その後、あなただけのクラスからメソッドを呼び出していることを確認するつもりはないことを前提としています。
(この答えはあなたがクラス自身のメソッドを呼び出すためのTypeError
を買ってあげるのPython 2.xではPythonの3.xのことをいう。)
例
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を、そして「ROLLCALLは」一つだけの引数を受け入れるように定義されている。
なお、rex.rollCall()は、正しい数の引数を送信するだろうが、今関数は、nが数値であることが期待犬のインスタンス(すなわち、レックス)を表すことになるNためにも例外が発生する原因となります。
装飾の出番これは、次のとおりです。 我々が「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
デコレータを使用する必要はありません。ただ、(自己パラメータを期待していない)と、クラスから呼び出すメソッドを宣言。デコレータはあなたにも(あなたがやりたいことはなかった)。
主に、あなただけしかし機能を使用して...
Pythonでそれは Python的<もう少しだが、の静的メソッド?の
それは私がそれらを呼び出すことができるようにPythonでの静的メソッドを持つことが可能です クラスの初期化せずに、同様ます:
ClassName.StaticMethod()
はい、静的メソッドは、(次のように作成することができます/>使用する)代わりの方法のためのキャメルケースの下線
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の2 str.maketrans()
モジュール内の関数であったのPython 3にstring
されます。
あなたは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
パッケージを作成し、もう1つは120 LOCを持っており、残りはせいぜい2ダースのLOCであるの9つのモジュールで終わります。私はこれで始まり、パッケージに変換し、唯一の真それらに値する獣のためのモジュールを作成することを好むます:
# 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 のデコレータます。
そこで、静的メソッドは、クラスのオブジェクトを作成せずに呼び出すことができる方法です。 例: -
@staticmethod
def add(a, b):
return a + b
b = A.add(12,12)
print b
上記の例では、メソッドadd
は、クラス名A
ないオブジェクト名によって呼び出されます。
Python の静的メソッドは 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行為の関数のすべての複素数に何らかの方法でます。