2012-03-20 1 views
2

함수/메소드를 검사하여 데코레이터로 사용할 수 있는지 여부를 확인할 수 있습니까? 그렇기 때문에 데코레이터가 다른 함수를 감싸고 호출 가능 함수를 반환하는 일반적인 방법을 따르고 있습니까? 특히 제 3 자 코드를 검증하려고합니다.메서드가 데코레이터인지 어떻게 알 수 있습니까?

+3

* 데코레이터로 사용할 수 있다는 것을 의미합니까 * * * 어딘가에 데코레이터로 사용되는 * 것을 말합니까? 첫 번째가 매우 어렵다는 것을 입증 할 수는 있지만, 일반적으로 풀기가 불가능하지는 않더라도 실제로 두 번째가 가능할 수 있습니다. –

+1

또는 함수가 꾸며져 있는지 묻고 있습니까? – forivall

+0

@ NiklasB. 죄송합니다 - 질문을 명확히했습니다. –

답변

2

, 당신은에 관해서는 추측을 생성 할 수 있습니다. 그러나 이것은 단지 추측 일 뿐이며 보장은 아닙니다.

그 외에도 파이썬 언어의 동적 유형 지정과 CPython 인터프리터에 내장 된 함수의 특수 처리로 인해 일반적으로 원하는 것을 믿을 수 없습니다. 호출 가능 객체가 다른 호출 가능 객체를 인자로 받아들이는지 또는 리턴 값이 가질 타입이 프로그램 적으로 알 수 없다. 또한 CPython에서 C로 구현 된 함수의 경우 호출 할 수있는 인수를 확인하기 위해 호출 가능한 함수를 검사 할 수도 없습니다.

"데코레이터"라는 단어는 다른 것을 의미 할 수 있습니다. 이것을 정의하는 한 가지 방법은 데코레이터가 단일 (호출 가능) 인수를 받아 호출 가능 함수를 반환하는 호출 가능 함수입니다.

이 정의에서 나는 "function"이라는 단어조차 사용하지 않았습니다. 그렇게하는 것은 실제로 부정확 할 것입니다.

  • 내장 classmethodstaticmethod 장식 돌아 기술자 객체가 아닌 기능 : 사실, 일반적으로 사용되는 장식 이상한 특성을 가지고있다.
  • 언어 버전 2.6이므로 함수와 메소드가 아닌 클래스를 꾸밀 수 있습니다.
  • __init__(self, somecallable) 메서드와 __call__(self, *args, **kwargs) 메서드를 포함하는 모든 클래스를 데코레이터로 사용할 수 있습니다.
+0

감사합니다 - 데코레이터가 "[호출 할 수있는 단일 인수를 받아들이고 호출 가능 번호를 반환하는 호출 가능] 일 수 있다는 진술은 내 테스트를위한 기초가 될 것이므로 유효성 검사에 충분할 것입니다. 타사 코드로 작성해야합니다. 그러나 복잡성으로 판단하여 대신 좋은 오류 메시지를 제공하려고합니다. :디 –

0

저는 이런 식으로 된 적이 없지만, 일반적으로 파이썬은 이와 같은 상황에서 "덕 타이핑"에 의존합니다. 따라서 더미 함수를 꾸미고 호출 가능 함수가 반환되는지 확인할 수 있습니다.

2

파이썬에는 표준화 된 데코레이터가 없으므로 찾고있는 데코레이터에 대해 알지 못하면 함수가 데코레이터인지 여부를 알 수있는 실제 방법이 없습니다.

데코레이터가 사용자가 제어 할 수있는 경우 데코 레이팅 된 기능임을 나타내는 표시를 추가 할 수 있습니다. 그렇지 않으면 이것을 수행하는 진정한 통일 된 방법이 없습니다. 예를 들어이 예제를 보자

def decorator(func): 
    return g 

@decorator 
def f() 
    pass 

def g(): 
    pass 

을 위의 예에서, 런타임에서, F 및 G는 동일합니다, 떨어져 두 이야기의 방법이 없습니다.

0

아니요. 불가능합니다. f이 데코레이터인지 확인하는 대신 확인해야하는 이유를 생각해야합니다.

일부 특정 장식을 기대하는 경우, 직접 당신이 어떤 특정 행동/방법을 원하는 경우/일부 호출 f가 장식으로 사용할 수 있는지

하여 검사 할 경우 확인 할 수 속성, 즉를 확인하실 수 있습니다 더미 함수를 전달하여 데코레이터 동작을 테스트 할 수 있지만 일반적으로 다른 입력에 대해 작동하지 않거나 동작이 다를 수 있습니다.

def decorator1(func): 
    def _wrapper(*args, **kwargs): 
     print "before" 
     func(*args, **kwargs) 
     print "after" 

    return _wrapper 

def dummy_func(): pass 

out_func = decorator1(dummy_func) 

if callable(out_func) and dummy_func != out_func: 
    print "aha decorated!" 
+0

'더미 함수를 넘겨 직접 확인할 수 있습니다 .' ?? 실제로 ... 당신은 그 주장과 관련하여 무엇을 말할 수는 없습니다! – katrielalex

+0

@katrielalex 네, 일반적인 대답은 No입니다. 그렇지만 장식자가하는 일을 알고 있다면 –

1

인수 오른쪽 번호와 어떤 호출이 장식로서 사용될 수있다 : 여기

는 이러한 검사 순이다. foo아무것도를 반환 할 수 있기 때문에

@foo 
def bar(...): 

는, 당연히

def bar(...): 
    ... 
bar = foo(bar) 

정확히 동일하다는 것을 기억하십시오, 당신은 기능이 장식되었는지의 여부를 확인하는 방법이 없습니다. foo은 훌륭하고 점수를 남길 수 있지만 그렇게 할 의무는 없습니다. 당신은 몇 가지 파이썬 코드를 부여하고 장식있는 모든 일을 찾으려면


, 당신은 그 장식 기능을 찾고 트리를 걸어 추상 구문 트리에 코드를 분석하여이를 수행 할 수 있습니다. 다음은 장식 자의 .id을 저장하는 예제입니다. 분명히 원하는 경우 ast 개체를 저장할 수 있습니다. 주어진 호출이 장식인지 아닌지, 의심 장식을 적용 예외를 잡기 후 결과가 __call__ 방법이 들어 있는지 여부를 테스트하여

>>> class DecoratorFinder(ast.NodeVisitor): 
...  def __init__(self, *args, **kwargs): 
...   super(DecoratorFinder, self).__init__(*args, **kwargs) 
...   self.decorators = set() 
...  
...  def visit_FunctionDef(self, node): 
...   self.decorators.update(dec.id for dec in node.decorator_list) 
...   self.generic_visit(node) 
... 
>>> finder = DecoratorFinder() 
>>> x = ast.parse(""" 
... @dec 
... def foo(): 
...  pass 
... """) 
>>> finder.visit(x) 
>>> finder.decorators 
set(['dec']) 
+0

을 사용하여 동작을 확인할 수 있습니다. 실제로 적어도 하나의 위치 인수를 취할 수있는 호출 가능 ... –

+0

@Niklas 당신은 물론 정확합니다 =) – katrielalex