2017-11-17 2 views
1

파이썬 장식자를 "다형성"으로 만드는 방법은 무엇입니까? 내 말은 데코 레이팅 된 함수의 정확한 하나의 매개 변수를 찾고, 그와 함께/함께 처리 한 다음 수정 된 매개 변수를 함수에 전달한다는 것입니다. 그러나 공통 이름을 가진이 매개 변수는 데코 레이팅 된 함수에서 임의의 위치를가집니다.데코 레이팅 된 함수의 임의의 위치 지정된 매개 변수가있는 파이썬 장식 자

+0

['inspect'] (https://docs.python.org/3/library/inspect.html)을 살펴볼 수 있습니다. –

답변

1

키워드 인수 (kwargs)를 사용하면 * kwargs가 데코레이터에서 키워드 인수의 이름과 값을 제공하기 때문에 쉽습니다.

func3(1,2,3,4,5,6,7,test="hallo") 

당신에게 줄 것이다 : 그래서 당신은이 같은 것을받을 그래서 당신은 그냥 "exactly_this_param"를 검색하고 바꿀 수

kwargs{'test': 'hallo'} 

..

하지만 당신이 사용하기로 결정했습니다 정상적인 args. 이것은 한 걸음 더 나아가서 가능합니다. > 당신을 제공합니다 -

  • 인수 :는 "비 키워드 인수"(인수)으로

    (I 파이썬 3를 사용) 당신이의 조합을 사용할 수 있습니다 : 그래서 여기

    이 가능한 솔루션입니다 이 func 호출의 실제 값의 튜플

  • func. 코드 .co_varnames -> 내가 그래서 당신은 "exactly_this_param의 인덱스를 찾을 수있는 가변적이고에 func_params

    func_params = func.__code__.co_varnames 
    

    그들을 할당

함수 정의에서 당신에게 인수 이름을 제공합니다 " in func. 코드 .co_varnames 그리고 정확히이 색인에서 args 값을 변경하십시오. 튜플은 파이썬에서 불변이기 때문에,

new_args[func_params.index("exactly_this_param")]=999 

또한 튜플에 목록으로 돌아 (new_args)와 인수을 변환해야이이 블록입니다.

이이 같은 (예를 들어, 코드 -하지만 실행) 결과 :

def decorator(func): 
def wrapped(*args, **kwargs): 
    # a tuple of the names of the parameters that func accepts 
    print(" ... decorator magic ....") 
    print(" .... args" + str(args)) 
    print(" .... kwargs" + str(kwargs)) 
    func_params = func.__code__.co_varnames 
    print(" .... param_names:" + str(func_params)) 
    # grab all of the kwargs that are not accepted by func 
    new_args=list(args) 
    new_args[func_params.index("exactly_this_param")]=999 
    args=tuple(new_args) 
    print(" .... new_args" + str(args)) 
    return func(*args, **kwargs) 
return wrapped 

@decorator 
def func1(a, b, exactly_this_param, c): 
    # does something 
    print("func1 => exactly_this_slightly_different_param: " + str(exactly_this_param)) 

@decorator 
def func2(exactly_this_param): 
    # does something 
    print("func2 => exactly_this_slightly_different_param: " + str(exactly_this_param)) 

@decorator 
def func3(a, b, c, d, e, exactly_this_param, *args, **kwargs): 
    # does something 
    print("func3 => exactly_this_slightly_different_param: " + str(exactly_this_param)) 

if __name__ == "__main__": 
    func1(1,2,3,4) 
    func2(12) 
    func3(1,2,3,4,5,6,7,test="hallo") 

결과 출력이 있었던 파라미터가 항상 발견하고 기반으로 999

c:\khz\devel>python test_dec.py 
    ... decorator magic .... 
    .... args(1, 2, 3, 4) 
    .... kwargs{} 
    .... param_names:('a', 'b', 'exactly_this_param', 'c') 
    .... new_args(1, 2, 999, 4) 
func1 => exactly_this_slightly_different_param: 999 
    ... decorator magic .... 
    .... args(12,) 
    .... kwargs{} 
    .... param_names:('exactly_this_param',) 
    .... new_args(999,) 
func2 => exactly_this_slightly_different_param: 999 
    ... decorator magic .... 
    .... args(1, 2, 3, 4, 5, 6, 7) 
    .... kwargs{'test': 'hallo'} 
    .... param_names:('a', 'b', 'c', 'd', 'e', 'exactly_this_param', 'args', 'kwargs') 
    .... new_args(1, 2, 3, 4, 5, 999, 7) 
func3 => exactly_this_slightly_different_param: 999 

대답으로 변경되는 것을 보여줍니다 this SO question.

관련 문제