답변:
네의 사용 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()
드물게 사용하십시오! 파이썬에서 정적 메소드가 필요한 상황은 극히 적으며, 별도의 "최상위"함수가 더 명확했던 여러 번 사용 된 것을 보았습니다.
정적 메소드는 내재 된 첫 번째 인수를받지 않습니다. 정적 메소드를 선언하려면 다음 관용구를 사용하십시오.
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
관계없이 이름의 첫 번째 매개 변수로 제공됩니다.
나는 Steven이 실제로 옳다고 생각한다 . 원래 질문에 대답하려면 클래스 메소드를 설정하려면 첫 번째 인수가 호출 인스턴스가 아니라고 가정하고 클래스에서 메소드 만 호출해야합니다.
(이 답변은 Python 3.x를 나타냅니다. Python 2.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이라는 두 개의 인수를 보내므로 "rollCall"은 하나의 인수 만 허용하도록 정의되므로 예외가 발생합니다.
또한, 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()
또는 type(my_t_instance).my_static_method()
이 명확 내가 정적 메소드를 호출하고 있습니다 것을 즉시 분명하게하기 때문에.
예, 정적 메소드 데코레이터를 확인하십시오 .
>>> class C:
... @staticmethod
... def hello():
... print "Hello World"
...
>>> C.hello()
Hello World
실제로 @staticmethod
데코레이터 를 사용할 필요는 없습니다 . 자체 매개 변수를 기대하지 않는 메서드를 선언하고 클래스에서 호출하면됩니다. 데코레이터는 인스턴스에서 호출 할 수있는 경우에만 있습니다 (원하는 것이 아니 었습니다)
대부분의 경우 함수를 사용합니다 ...
class Dummy: def static1(): print "hello from static1" @staticmethod def static2(): print "hello from static2" Dummy.static2() Dummy.static1()
출력 : hello from static2 Traceback <가장 최근 호출> : <모듈>의 46 번째 줄 "ll.py"Dummy.static1 () TypeError : unbound method static1 ()은 더미 인스턴스와 함께 첫 번째 인수로 호출 됨 (아무것도 얻지 않음)
self
당신이 지시하지 않는 한 첫 번째 인수로 전달할 것 입니다. (참조 : decorator)
self
호출 방법에 따라 적절하게 참조 를 삽입합니다 . 테스트 케이스 : pastebin.com/12DDV7DB .
staticmethod
장식 하나는 클래스 인스턴스 (인스턴스에 대한 함수를 호출 할 때이 액 실패) 모두에 대한 함수를 호출 할 수있다.
class C: def callme(): print('called'); C.callme()
파이썬의 정적 메소드?
파이썬에서 정적 메소드를 가질 수 있으므로 클래스를 초기화하지 않고 호출 할 수 있습니다.
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
은입니다. 차이점은 classmethod가 클래스를 암시 적 첫 번째 인수로 가져오고 서브 클래스 화하면 하위 클래스를 암시 적 첫 번째 인수로 가져옵니다.
class ClassName(object):
@classmethod
def class_method(cls, kwarg1=None):
'''return a value that is a function of the class and kwarg1'''
참고 cls
첫 번째 인수의 필수 이름이 아닙니다,하지만 당신은 무엇을 사용하는 경우 가장 경험이 풍부한 파이썬 코더가 심하게 이루어 고려할 것입니다.
이들은 일반적으로 대체 생성자로 사용됩니다.
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
패키지를 만들고 그 중 하나는 120 개의 LOC를 갖고 나머지는 최대 24 개의 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 () 사용
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()
는 없지만 어쨌든 나쁜 습관으로 간주되며 컴파일러는 항상 그것에 대해 경고합니다.