내가 매우 일반적인 것을하는 데코레이터를 작성했다고 가정하자. 예를 들어 모든 인수를 특정 유형으로 변환하고, 로깅을 수행하고, 메모 화를 구현할 수 있습니다.
다음은 예입니다.
def args_as_ints(f):
def g(*args, **kwargs):
args = [int(x) for x in args]
kwargs = dict((k, int(v)) for k, v in kwargs.items())
return f(*args, **kwargs)
return g
@args_as_ints
def funny_function(x, y, z=3):
"""Computes x*y + 2*z"""
return x*y + 2*z
>>> funny_function("3", 4.0, z="5")
22
지금까지 모든 것이 잘되었습니다. 그러나 한 가지 문제가 있습니다. 데코 레이팅 된 함수는 원래 함수의 문서를 유지하지 않습니다.
>>> help(funny_function)
Help on function g in module __main__:
g(*args, **kwargs)
다행히 해결 방법이 있습니다.
def args_as_ints(f):
def g(*args, **kwargs):
args = [int(x) for x in args]
kwargs = dict((k, int(v)) for k, v in kwargs.items())
return f(*args, **kwargs)
g.__name__ = f.__name__
g.__doc__ = f.__doc__
return g
@args_as_ints
def funny_function(x, y, z=3):
"""Computes x*y + 2*z"""
return x*y + 2*z
이번에는 함수 이름과 문서가 정확합니다.
>>> help(funny_function)
Help on function funny_function in module __main__:
funny_function(*args, **kwargs)
Computes x*y + 2*z
그러나 여전히 문제가 있습니다. 함수 서명이 잘못되었습니다. 정보 "* args, ** kwargs"는 쓸모가 없습니다.
무엇을해야합니까? 간단하지만 결함이있는 두 가지 해결 방법을 생각할 수 있습니다.
1-독 스트링에 올바른 서명을 포함합니다.
def funny_function(x, y, z=3):
"""funny_function(x, y, z=3) -- computes x*y + 2*z"""
return x*y + 2*z
중복으로 인해 좋지 않습니다. 서명은 여전히 자동으로 생성 된 문서에 제대로 표시되지 않습니다. 함수를 업데이트하고 독 스트링 변경을 잊어 버리거나 오타를 만드는 것은 쉽습니다. [ 그리고 예, 독 스트링이 이미 함수 본문을 복제한다는 사실을 알고 있습니다. 이것을 무시하십시오; funny_function은 임의의 예입니다. ]
2-데코레이터를 사용하지 않거나 모든 특정 시그니처에 특수 목적의 데코레이터를 사용합니다.
def funny_functions_decorator(f):
def g(x, y, z=3):
return f(int(x), int(y), z=int(z))
g.__name__ = f.__name__
g.__doc__ = f.__doc__
return g
이것은 동일한 서명을 가진 함수 세트에 대해 잘 작동하지만 일반적으로 쓸모가 없습니다. 처음에 말했듯이 데코레이터를 완전히 일반적으로 사용할 수 있기를 원합니다.
완전히 일반적이고 자동 인 솔루션을 찾고 있습니다.
그래서 질문은 : 데코 레이팅 된 함수 시그니처가 생성 된 후 편집 할 수있는 방법이 있습니까?
그렇지 않으면, 데코 레이팅 된 함수를 구성 할 때 함수 시그니처를 추출하고 "* kwargs, ** kwargs"대신 해당 정보를 사용하는 데코레이터를 작성할 수 있습니까? 그 정보를 어떻게 추출합니까? exec로 데코 레이팅 된 함수를 어떻게 구성해야합니까?
다른 방법은 없나요?
inspect.Signature
장식 된 기능을 처리하는 데 무엇이 추가 되었는지 다소 궁금했습니다 .