默认参数装饰器python [英] Default Argument decorator python
问题描述
Python 3.6
Python 3.6
我正在尝试创建一个装饰器,该装饰器自动将参数的字符串分配为默认值。
I'm attempting to create a decorator that automatically assigns the string of the argument as the default value.
例如:
def example(one='one', two='two', three='three'):
pass
等同于:
@DefaultArguments
def example(one, two, three):
pass
这是我的尝试(尚不可行...) DefaultArguments
:
Here is my attempt (doesn't work.. yet..) DefaultArguments
:
from inspect import Parameter, Signature, signature
class DefaultArguments(object):
@staticmethod
def default_signature(signature):
def default(param):
if param.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.POSITIONAL_ONLY):
return param.replace(default=param.name)
else:
return param
return Signature([default(param) for param in signature.parameters.values()])
def __init__(self, func):
self.func = func
self.sig = self.default_signature(signature(func))
def __call__(self, *args, **kwargs):
arguments = self.sig.bind(*args, **kwargs)
return self.func(arguments)
静态方法 default_signature
为该函数创建所需的签名,但是我很难为该函数分配新的签名。我正在尝试使用签名。绑定
我已经阅读了文档但我遗漏了一些东西。
The staticmethod default_signature
creates the desired signature for the function, but I'm having difficulty assigning the new signature to the function. I'm trying to use Signature.bind
I've read the docs but i'm missing something.
EDIT
包含Ashwini Chaudhary的答案:
Incorporating Ashwini Chaudhary's answer:
from inspect import Parameter, Signature, signature
class DefaultArguments(object):
@staticmethod
def default_signature(signature):
def default(param):
if param.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.POSITIONAL_ONLY):
return param.replace(default=param.name)
else:
return param
return Signature([default(param) for param in signature.parameters.values()])
def __init__(self, func):
self.func = func
self.sig = self.default_signature(signature(func))
print(self.sig)
def __call__(self, *args, **kwargs):
ba = self.sig.bind(*args, **kwargs)
ba.apply_defaults()
return self.func(*ba.args, **ba.kwargs)
推荐答案
之后将args和关键字与签名绑定在一起,您需要调用 <$ apply_defaults > BoundArguments
实例设置缺少参数的默认值。
After binding the args and keywords with the signature you need to call apply_defaults
on the BoundArguments
instance to set the default values for missing arguments.
该函数调用还将使用 BoundArguments
的 args
和 kwargs
属性进行调用。
Also the function call will be invoked using BoundArguments
's args
and kwargs
properties.
def __call__(self, *args, **kwargs):
ba = self.sig.bind(*args, **kwargs)
ba.apply_defaults()
return self.func(*ba.args, **ba.kwargs)
演示:
>>> @DefaultArguments
... def example(one, two, three):
... print(one, two, three)
...
>>> example()
one two three
>>> example('spam')
spam two three
>>> example(one='spam', three='eggs')
spam two eggs
您的代码的功能版本还可以更新修饰函数的签名:
A functional version of your code that also updates the signature of the decorated function:
from functools import wraps
from inspect import Parameter, Signature, signature
def default_arguments(func):
def default(param):
if param.kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.POSITIONAL_ONLY):
param = param.replace(default=param.name)
return param
sig = Signature([default(param) for param in signature(func).parameters.values()])
@wraps(func)
def wrapper(*args, **kwargs):
ba = sig.bind(*args, **kwargs)
ba.apply_defaults()
return func(*ba.args, **ba.kwargs)
wrapper.__signature__ = sig
return wrapper
演示:
>>> from inspect import getfullargspec
>>> @default_arguments
... def example(one, two, three):
... print(one, two, three)
...
>>> getfullargspec(example)
FullArgSpec(
args=['one', 'two', 'three'],
varargs=None,
varkw=None,
defaults=('one', 'two', 'three'),
kwonlyargs=[], kwonlydefaults=None, annotations={}
)
这篇关于默认参数装饰器python的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!