클래스 본문 내에서 정적 메소드를 사용하려고 할 때 내장 staticmethod
함수를 장식 자로 사용하여 정적 메소드를 다음과 같이 정의하십시오 .
class Klass(object):
@staticmethod # use as decorator
def _stat_func():
return 42
_ANS = _stat_func() # call the staticmethod
def method(self):
ret = Klass._stat_func() + Klass._ANS
return ret
다음과 같은 오류가 발생합니다.
Traceback (most recent call last):<br>
File "call_staticmethod.py", line 1, in <module>
class Klass(object):
File "call_staticmethod.py", line 7, in Klass
_ANS = _stat_func()
TypeError: 'staticmethod' object is not callable
왜 이런 일이 발생하는지 이해하고 (descriptor binding)_stat_func()
마지막 사용 후 정적 메소드 로 수동으로 변환 하여 해결할 수 있습니다 .
class Klass(object):
def _stat_func():
return 42
_ANS = _stat_func() # use the non-staticmethod version
_stat_func = staticmethod(_stat_func) # convert function to a static method
def method(self):
ret = Klass._stat_func() + Klass._ANS
return ret
그래서 내 질문은 :
더 깨끗하거나 더 많은 “Pythonic”에서와 같이 더 나은 방법이 있습니까?
답변
staticmethod
객체 __func__
에는 원래 원시 함수를 저장 하는 속성 이있는 것 같습니다 (그렇게해야한다는 의미가 있습니다). 그래서 이것은 작동합니다 :
class Klass(object):
@staticmethod # use as decorator
def stat_func():
return 42
_ANS = stat_func.__func__() # call the staticmethod
def method(self):
ret = Klass.stat_func()
return ret
옆으로 정적 메서드 객체에 원래 함수를 저장하는 일종의 속성이 있다고 생각했지만 구체적인 내용은 알지 못했습니다. 누군가에게 물고기를주는 대신 물고기를 가르치는 정신으로, 이것이 내가 조사하고 찾은 것입니다 (파이썬 세션의 C & P).
>>> class Foo(object):
... @staticmethod
... def foo():
... return 3
... global z
... z = foo
>>> z
<staticmethod object at 0x0000000002E40558>
>>> Foo.foo
<function foo at 0x0000000002E3CBA8>
>>> dir(z)
['__class__', '__delattr__', '__doc__', '__format__', '__func__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> z.__func__
<function foo at 0x0000000002E3CBA8>
대화식 세션에서 비슷한 종류의 파기 ( dir
매우 도움이 됨)는 종종 이러한 종류의 질문을 매우 빠르게 해결할 수 있습니다.
답변
이것이 내가 선호하는 방식입니다.
class Klass(object):
@staticmethod
def stat_func():
return 42
_ANS = stat_func.__func__()
def method(self):
return self.__class__.stat_func() + self.__class__._ANS
DRY 원칙Klass.stat_func
때문에이 솔루션을 선호합니다 . Python 3에 새로운 기능이있는 이유 를 상기시킵니다. 🙂super()
그러나 나는 다른 것에 동의합니다. 일반적으로 가장 좋은 선택은 모듈 수준 기능을 정의하는 것입니다.
예를 들어 @staticmethod
함수를 사용하면 재귀가 잘 보이지 않을 수 있습니다 ( Klass.stat_func
inside 를 호출하여 DRY 원리를 깨야합니다 Klass.stat_func
). self
내부 정적 메서드에 대한 참조가 없기 때문 입니다. 모듈 레벨 기능을 사용하면 모든 것이 정상으로 보입니다.
답변
클래스 정의 후에 클래스 속성을 주입하는 것은 어떻습니까?
class Klass(object):
@staticmethod # use as decorator
def stat_func():
return 42
def method(self):
ret = Klass.stat_func()
return ret
Klass._ANS = Klass.stat_func() # inject the class attribute with static method value
답변
이것은 staticmethod가 디스크립터이기 때문에 디스크립터 프로토콜을 실행하고 실제 호출 가능을 얻으려면 클래스 레벨 속성 페치가 필요합니다.
소스 코드에서 :
클래스 (예 🙂
C.f()
또는 인스턴스 (예 :)에서 호출 할 수 있습니다C().f()
. 클래스를 제외하고 인스턴스는 무시됩니다.
그러나 클래스가 정의되는 동안 클래스 내부에서 직접하지는 않습니다.
그러나 한 논평자가 언급했듯이 이것은 실제로 “Pythonic”디자인이 아닙니다. 대신 모듈 레벨 기능을 사용하십시오.
답변
이 솔루션은 어떻습니까? @staticmethod
데코레이터 구현 에 대한 지식에 의존하지 않습니다 . 내부 클래스 StaticMethod는 정적 초기화 함수의 컨테이너로 재생됩니다.
class Klass(object):
class StaticMethod:
@staticmethod # use as decorator
def _stat_func():
return 42
_ANS = StaticMethod._stat_func() # call the staticmethod
def method(self):
ret = self.StaticMethod._stat_func() + Klass._ANS
return ret
답변
