默认参数装饰器python [英] Default Argument decorator python

查看:107
本文介绍了默认参数装饰器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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆