如何在不调用函数的情况下调用Python的内置函数参数验证?

2024-04-19 22:55:53 发布

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

Python显然有一种方法可以验证函数调用是否有有效的参数(正确数量的位置参数、正确的关键字参数等)。下面是我的意思的一个基本例子:

def test_func(x, y, z=None):
    print(x, y, z)

test_func(2)  # Raises a "missing positional argument" TypeError
test_func(1, 2, 3, a=5)  # Raises an "unexpected keyword argument" TypeError

有没有一种方法,我可以使用这个参数验证,而不实际调用函数?你知道吗

我基本上是在编写一个decorator,在调用包装函数本身之前,它会根据函数参数执行一些预处理步骤,例如:

def preprocess(func):
    def wrapper(*args, **kwargs):
        # Verify *args and **kwargs are valid for the original function.
        # I want the exact behavior of calling func() in the case of bad arguments,
        # but without actually calling func() if the arguments are ok.

        preprocess_stuff(*args, **kwargs)
        func(*args, **kwargs)
    return wrapper

我希望我的wrapper函数在执行任何预处理工作之前验证参数是否有效(如果在包装函数上使用)。你知道吗

我想利用Python在每次调用函数时已经进行的检查以及它将引发的各种异常。我只是不想调用函数,因为函数可能不是幂等的。写我自己的检查和例外感觉像是重新发明轮子。你知道吗


Tags: the方法函数test参数defargsargument
1条回答
网友
1楼 · 发布于 2024-04-19 22:55:53

如果不调用函数,就不能调用函数的实际内置参数验证,但是可以使用非常接近的方法。你知道吗

^{}模块有一个函数^{},它返回一个^{}对象,表示传递给它的函数的参数签名。该Signature对象有一个^{}方法,该方法试图使用传递给它的参数创建一个^{}对象。如果这些参数与签名不匹配,则引发TypeError。你知道吗

虽然这主要表现为内置参数绑定逻辑,但它有一些区别。例如,它不能总是确定用C编写的函数的签名,它与decorator的交互将取决于它们是否使用^{}(或者其他设置__wrapped__属性的东西)。也就是说,因为实际参数绑定逻辑是不可访问的,inspect.signature是最好的选择。你知道吗

我们可以用这些来创建您的装饰器:

import functools
import inspect

def preprocess(func):
    sig = inspect.signature(func)
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        try:
            sig.bind(*args, **kwargs)
        except TypeError:
            pass  # bad arguments; skip preprocessing
        else:
            print("Preprocessing: args=%r, kwargs=%r" % (args, kwargs))
            # ... etc.
        return func(*args, **kwargs)
    return wrapper

用法:

@preprocess
def test_func(x, y, z=None):
    print(x, y, z)

你知道吗

>>> test_func(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in wrapper
TypeError: test_func() missing 1 required positional argument: 'y'

你知道吗

>>> test_func(1, 2, 3, a=5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in wrapper
TypeError: test_func() got an unexpected keyword argument 'a'

你知道吗

>>> test_func(1, 2)
Preprocessing: args=(1, 2), kwargs={}
1 2 None

请注意,如果提供了错误的参数,实际上您确实希望调用函数,因为您“希望在参数错误的情况下调用func()的确切行为”(引用您的注释),而获得调用任意函数的确切行为(即使该行为立即失败)的唯一方法是实际上是这样。在这种情况下,您不想做的是预处理,这是上面的decorator为您实现的。你知道吗

相关问题 更多 >