2010-06-30 3 views
3

함수에 대한 특정 인수가 몇 가지 기준을 통과하는지 테스트하는 파이썬 함수 데코레이터를 작성하고 싶습니다. 예를 들어, 다음 내가파이썬의 데코레이터에 특정 인수를 전달하는 방법

def ensure_even(n) : 
    def decorator(function) : 
    @functools.wraps(function) 
    def wrapper(*args, **kwargs): 
     assert(n % 2 == 0) 
     return function(*args, **kwargs) 
    return wrapper 
    return decorator 


@ensure_even(arg2) 
def foo(arg1, arg2, arg3) : pass 

@ensure_even(arg3) 
def bar(arg1, arg2, arg3) : pass 

를이 (유효하지 파이썬 코드) 같은 것을 할 수 있도록하려면, 내가 어떤 인수도 항상하는지 테스트한다고 가정하지만 위를 달성하는 방법을 알아낼 수 없습니다. 데코레이터에 특정 인수를 전달하는 방법이 있습니까? (위의 foo와 arg3에 대한 arg2와 같은)

고마워!

+0

파라 메트릭 데코레이터를 만드는 유일한 방법은 중첩 된 데코레이터를 사용하는 것입니다. –

답변

11

이 작업을 수행 할 수 있습니다

def ensure_even(argnum): 
    def fdec(func): 
    def f(*args, **kwargs): 
     assert(args[argnum] % 2 == 0) #or assert(not args[argnum] % 2) 
     return func(*args, **kwargs) 
    return f 
    return fdec 

을 그럼 :

@ensure_even(1) #2nd argument must be even 
def test(arg1, arg2): 
    print(arg2) 

test(1,2) #succeeds 
test(1,3) #fails 
+0

네, 그게 내가 한 일입니다.하지만 이건 제 C++ 배경이 더 우아한 파이썬 방법 대신에 해킹으로 떠오르고 있다고 생각했습니다 :) 어쨌든 고마워요. –

+1

@MK : 위치 인수 대신 키워드 인수를 사용하는 경우 키워드 인수의 이름을'ensure_even'으로 전달할 수 있습니다. 그건 하드 코딩 된 숫자가 적고 argnum을 바꿀 필요없이 새로운 args를 추가해도 코드가 살아남을 수 있다는 점에서 의미가 있습니다. – unutbu

+0

@ ~ unutbu 그래, 그게 좋은 방법이야. – jcao219

4

내 이전의 대답은 질문의 요점을 놓쳤다.

는 여기에 더 이상 해결책 :

def ensure_even(*argvars): 
    def fdec(func): 
    def f(*args,**kwargs): 
     for argvar in argvars: 
     try: 
      assert(not args[func.func_code.co_varnames.index(argvar)] % 2) 
     except IndexError: 
      assert(not kwargs[argvar] % 2) 
     return func(*args,**kwargs) 
    return f 
    return fdec 

등이 사용이다 : 나는 모든 상황에서 작동하는지 모르겠어요하지만

@ensure_even('a','b') 
def both_even(a,b): 
    print a,b 

@ensure_even('even') 
def first_even(even, arg2): 
    print even, arg2 

both_even(2,2) 
first_even(2,3) 
both_even(2,1) #fails 

은.

+0

아 인트로 스펙 션. 나는 위의 것이 무엇을하고 있는지를 먼저 알아 내야했다. 그러나 나는 아이디어를 얻었고 그것은 차갑다. 위의 솔루션을 계속 사용할 예정입니다. –

관련 문제