繁体   English   中英

Python中验证的函数参数

[英]Validated Function Arguments in Python

我有一个功能

def func(a,b,c,d):
    ...

我正在尝试编写一个了解参数的装饰器,并将其中一些记录到另一个系统中。

def decorator(func):
    def new_func(*args, **kwargs):
        if (func.__name__ == 'func'):
            a = ?
            b = ?
            c = ?
            d = ?
        else:
            a = ?
            b = ?
            c = ?
            d = ?
        log_to_system(a, b, c, d)
        return func(*args, **kwargs)
return new_func

问题是装饰器没有一种简单的方法从args和kwargs中提取a,b,c,d值,因为用户可以使用位置或关键字参数传递这些值。 我也希望保持这种通用性,因为这个装饰器可以用于各种不同的功能。

是否有一个库或实用程序可以轻松地从args和kwargs中提取参数的值?

一个简单的方法是让你的log_to_system函数接受变量参数和变量关键字参数以及它实际记录的已知参数,这样你就可以简单地将变量参数和变量关键字参数从装饰函数传递给log_to_system并让解释器为您提取参数abcd

def log_to_system(a, b, c, d, *args, **kwargs):
    print(a, b, c, d)

def decorator(func):
    def new_func(*args, **kwargs):
        log_to_system(*args, **kwargs)
        return func(*args, **kwargs)
    return new_func

@decorator
def func(a, b, c, d, e):
    pass

func(1, 2, c=3, d=4, e=5)

这输出:

1 2 3 4

或者,您可以使用inspect.signature在将给定的变量参数和关键字参数绑定到装饰函数的签名之后获取参数的dict,以便您可以仅使用所需的参数调用log_to_system

import inspect

def log_to_system(a, b, c, d):
    print(a, b, c, d)

def decorator(func):
    sig = inspect.signature(func)
    def new_func(*args, **kwargs):
        arguments = sig.bind(*args, **kwargs).arguments
        log_to_system(**{k: arguments[k] for k in log_to_system.__code__.co_varnames})
        return func(*args, **kwargs)
    return new_func

@decorator
def func(a, b, c, d, e):
    pass

func(1, 2, c=3, d=4, e=5)

这输出:

1 2 3 4

您可以使用inspect ,工作示例:

import inspect


def deco(func):
    signature = inspect.signature(func)

    def _deco(*args, **kwargs):
        binded = signature.bind(*args, **kwargs)
        arguments = binded.arguments  # OrderedDict
        print(arguments.items())
        return func(*args, **kwargs)

    return _deco


@deco
def foo(a, b, c, d):
    pass


@deco
def bar(d, c, b, a):
    pass


foo(1, 2, c=3, d=4)  # odict_items([('a', 1), ('b', 2), ('c', 3), ('d', 4)])
bar(1, a=2, b=3, c=4)  # odict_items([('d', 1), ('c', 4), ('b', 3), ('a', 2)])

您可以使用此通用装饰器来转储参数值:

def dump_args(func):
    # Decorator to print function call details - parameters names and effective values
    def wrapper(*func_args, **func_kwargs):
        arg_names = func.__code__.co_varnames[:func.__code__.co_argcount]
        args = func_args[:len(arg_names)]
        defaults = func.__defaults__ or ()
        args = args + defaults[len(defaults) - (func.__code__.co_argcount - len(args)):]
        params = list(zip(arg_names, args))
        args = func_args[len(arg_names):]
        if args: params.append(('args', args))
        if func_kwargs: params.append(('kwargs', func_kwargs))
        return func(*func_args, **func_kwargs)
    return wrapper

Credits属于@aliteralmind,他在这篇StackOverflow 帖子中建议了这个装饰器。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM