Pythonic编写包装函数的方法

Dot*_*tan 5 python

假设我有一个foo获取一些参数的函数

def foo(width, height, depth=0):
    ...
Run Code Online (Sandbox Code Playgroud)

我想编写一个包装器函数来获取所有foo参数并将它们传递给它,例如

def goo(width, height, depth=0):
    ...
    foo(width, height, depth)
    ...
Run Code Online (Sandbox Code Playgroud)

但这很难看,因为我必须重复变量默认值.

在python中执行此操作的惯用方法是什么?

我想到的几个选项:

  1. 传递到goo一个叫做foo_params和调用的字典,foo(**foo_params)但后来很容易出错,因为我不知道所有的参数都在那里

  2. 为foo编写另一个包装器,用于检查具有默认值的参数是否为None,如果是,则不传递它们

  3. 将默认值作为常量,所以我不会重复它们

Chr*_*ean 6

您可以使用*args**kwargs语法传递未知数量的参数和/或关键字参数:

>>> def dec(func):
    def inner(*args, **kwargs):
        print('decorated function')
        func(*args, **kwargs)
    return inner

>>> @dec
def func(a, b):
    return a + b

>>> func(1, 2)
decorated function
>>> 
Run Code Online (Sandbox Code Playgroud)

一个缺点使用*args,并**kwargs是,你会失去装饰功能的原单函数签名.例如:

>>> help(func)
Help on function inner in module __main__:

inner(*args, **kwargs)

>>> 
Run Code Online (Sandbox Code Playgroud)

解决方案是使用functools.wraps().它基本上将装饰函数中的数据复制到包装函数:

>>> from functools import wraps
>>> 
>>> def dec(func):
    @wraps(func)
    def inner(*args, **kwargs):
        print('decorated function')
        func(*args, **kwargs)
    return inner

>>> @dec
def func(a, b):
    return a + b

>>> func(1, 2)
decorated function
>>> 
Run Code Online (Sandbox Code Playgroud)

您可以在下面看到,如果您现在可以显示help(func)原始签名func:

>>> help(func)
Help on function func in module __main__:

func(a, b)

>>>
Run Code Online (Sandbox Code Playgroud)