我可以从被调用函数内部区分位置参数和关键字参数吗?

2024-04-26 09:28:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我想反对Python库中函数的旧语法。为了有效地检测是否有人在使用旧语法,我需要知道参数是按位置调用还是通过关键字调用。有没有办法检测到这一点

作为一个例子,考虑这个函数:

def store(name='', value=0):
    # Some functionality here...

此函数是否可以知道是否已这样调用它:

store('ben', 5)

还是像这样

store(name='ben', value=5)

Tags: store函数name参数herevaluedef语法
2条回答

您可以将*args添加到函数的参数中,并检查其中是否包含任何参数-如果是,则用户向函数传递的位置参数应作为关键字参数传递:

def store(*args, name='', value=0):
    if args: # args is not empty - user passed deprecated positional arguments
        print(f"Warning: you passed the arguments {' and '.join(map(str, args))} as positional arguments.")
        print("This is deprecated - please pass them as keyword arguments")
        name = args[0]
        if len(args) >= 2:
            value = args[1]

store('ben', 5)
store(name='ben', value=5)

在交互式Python控制台中测试:

>>> store('ben', 5)
Warning: you passed the arguments ben and 5 as positional arguments.
This is deprecated - please pass them as keyword arguments
>>> store('ben', value=5)
Warning: you passed the arguments ben as positional arguments.
This is deprecated - please pass them as keyword arguments
>>> store(name='ben', value=5)
>>>

我将创建一个包含所有弃用检查逻辑的装饰器:

from functools import wraps


def _positional_arg_warning(args, func):
    varnames = func.__code__.co_varnames

    pos_varnames = ', '.join(varnames[:len(args)])

    msg = (
        f'Warning: positional arguments `{pos_varnames}` for `{func.__qualname__}` '
        'are deprecated.  Please use keyword arguments instead.'
    )
    print(msg)


def args_deprecated(func):

    @wraps(func)
    def wrapper(*args, **kwargs):
        # call the function first, to make sure the signature matches
        ret_value = func(*args, **kwargs)

        if args:
            _positional_arg_warning(args, func)

        return ret_value
    return wrapper

现在,您可以包装任何将不推荐其位置参数的函数:

@args_deprecated
def some_func(a, b, c=None):
    pass

>>> some_func('aa', 'bb', c='cc')
Warning: positional arguments a, b for `some_func` are deprecated.  
Please use keyword arguments instead.
>>>
>>> some_func(a='aa', b='bb', c='cc')
>>>

相关问题 更多 >