2017-10-24 19 views
2

*args**kwargs 만 입력하면 데코레이터를 사용하고 일부 변경을 수행 한 다음 원래의 함수를 위치 및 방향과 함께 호출합니다. 데코 레이팅 된 함수의 명명 된 인수는 변경되지 않았습니다.장식 자의 * args 및 ** kwargs 만 처리하고 다른 인자는 그대로 두는 방법

인수의 변경은 을 args 앞에두고 dict의 키를 kwargs으로 앞에 붙이는 것입니다.

예.

여기 pos1, pos2named1
from decorator import decorator 

@decorator 
def prepare_opts(decorated_func, *args, **kwargs): 
    prepared_args = prepare_single_opt_keys(args) 
    prepared_kwargs = prepare_named_opt_keys(kwargs) 

    return decorated_func(*prepared_args, **prepared_kwargs) 

@my_decorator 
def func1(pos1, pos2, *args, named1=None, **kwargs): 
    ...do stuff 

이 장식에 의해 무시되어야한다 :이 같은이 장식을 사용하고 싶습니다. 데코레이터는 pos1{'--named1': 'foobar', '--foo': 'bar'}('--foo', '--bar', '--foo', '--bar')을 통과,

func1('foo', 'bar', named1='foobar', ('--foo', '--bar'), {'--foo': 'bar'}) 

그러나 이것은 분명히 작동하지 않을 수 있습니다

그래서이 같은 func1에 호출 :

func1('foo', 'bar', 'foo', 'bar', named1='foobar', foo='bar') 

이 같은 장식 된 함수를 호출해야 pos2. 모두가이 있는지,

@decorator 
def prepare_opts(decorated_func, pos1, pos2, *args, named1, **kwargs): 
    prepared_args = prepare_single_opt_keys(args) 
    prepared_kwargs = prepare_named_opt_keys(kwargs) 

    return decorated_func(pos1, pos2, *prepared_args, named1, **prepared_kwargs) 

그러나 여기서 문제는, 내가 다른 기능의 많은 일을 할 수있는 장식을 원하는 :

이 난에 장식을 변경하면 내가 올바른 인수를 얻을 수 있다는 사실을 알고 위치 및 명명 된 매개 변수의 수와 추가 *args**kwargs. 내 질문의

요약 : 이 장식 된 함수의 위치 및 명명 된 인수 중 하나를 건드리지 않고 내 Decoratorfunction의 *args/**kwargs -Arguments 사람들을 소모하지 않고 장식에 *args**kwargs을 구문 분석 할 수있는 방법이 있습니까?

+0

나는 정말로 이것들 ([1] (https://stackoverflow.com/questions/147816/preserving-signatures-of-decorated-functions), [2] (https : // stackoverflow. com/questions/18906760/parsing-args-and-kwargs-in-decorators))는 문제에 대한 정확한 해결책을 담고 있지만 적어도 관련이 있으며 유용한 통찰력을 제공 할 수 있습니다. 특히, 최소한''decorator'' (https://pypi.python.org/pypi/decorator) 모듈을 체크 할 필요가 있습니다. –

답변

1

inspect.getargspec 기능을 사용해보십시오. 나는 그것을 테스트하지 않았지만이 접근법을 사용할 수 있습니다.

import inspect 

def your_decorator(func): 
    func_args = inspect.getargspec(func)[0] 
    args_number = len(func_args) 

    def wrapper(*args, **kwargs): 
     if len(args) > args_number: 
      args[args_number:] = prepare_single_opt_keys(args[args_number:]) 
     optional_kwargs = {k: kwargs.pop(k) for k in kwargs if k not in func_args} 
     prepared_kwargs = prepare_named_opt_keys(optional_kwargs) 
     kwargs.update(prepared_kwargs) 
     return func(*args, **kwargs) 
    return wrapper 

그러나 나는 당신이 그것을 필요로하지 않는다고 확신합니다. 이런 종류의 내성 검사는 거의 항상 피해야합니다.

+0

약간 수정 된 버전이 저에게 효과적입니다. 내성을 사용하는 것이 거의 항상 피할 수 있다고 말하면서도 이것을 수행하는 또 다른 "우수 사례"가있는 경우 1-2 일을 기다립니다. 더 좋은 아이디어가 나오지 않으면, 대답을 받아 들여 python3과 작동하도록 변경 사항을 추가 할 것입니다. – Igle

+0

예제에서 py3에서는 작동하지 않는 것은 무엇입니까? – Raz

+1

inspect 패키지에서 getargspec :'주석 또는 키워드 전용 매개 변수를 지원하지 않으므로이 함수는 더 이상 사용되지 않으며, 제공된 callable에 이 있으면 ValueError가 발생합니다 .' – Igle