为不同函数分离**kwargs

17 投票
3 回答
4912 浏览
提问于 2025-04-18 05:08

假设有一个高级函数,它可以接收多个函数作为参数,那么这个函数怎么能把关键字参数传递给这些函数呢?

举个例子

def eat(food='eggs', how_much=1):
    print(food * how_much)


def parrot_is(state='dead'):
    print("This parrot is %s." % state)


def skit(*lines, **kwargs):
    for line in lines:
        line(**kwargs)

skit(eat, parrot_is)  # eggs \n This parrot is dead.
skit(eat, parrot_is, food='spam', how_much=50, state='an ex-parrot') # error

state 不是 eat 函数的关键字参数,那这样一来,skit 是怎么只把和它调用的函数相关的关键字参数传递过去的呢?

3 个回答

-1

这个代码定义了一个叫做`sample`的函数,它有三个参数:`a`、`b`和`c`。其中,`c`是一个可选参数,默认值是0。

* -> 在参数前面是位置参数,在参数后面是关键字参数

下面是一些调用这个函数的例子:

sample(1,2,c=10) 这行代码调用了`sample`函数,给`a`传了1,给`b`传了2,给`c`传了10。

sample(a=1,b=2,c=1) 这行代码也可以正常工作,因为我们用关键字的方式给每个参数赋值。

sample(1,2,c) 这行代码会出错,提示“TypeError”,意思是`sample`函数只接受两个位置参数,但这里给了三个参数。

8

如果你在所有的定义里加上 **kwargs,那么你就可以把所有的参数都传进去:

def eat(food='eggs', how_much=1, **kwargs):
    print(food * how_much)


def parrot_is(state='dead', **kwargs):
    print("This parrot is %s." % state)


def skit(*lines, **kwargs):
    for line in lines:
        line(**kwargs)

**kwargs 里,如果有一些参数不是明确指定的关键字参数,它们就会被留在 kwargs 里,而像 eat 这样的函数会忽略这些参数。

举个例子:

>>> skit(eat, parrot_is, food='spam', how_much=50, state='an ex-parrot')
spamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspamspam
This parrot is an ex-parrot.
16

你可以根据一个函数的 func_code.co_varnames(在 Python 2 中)来筛选 kwargs 字典里的内容:

def skit(*lines, **kwargs):
    for line in lines:
        line(**{key: value for key, value in kwargs.iteritems() 
                if key in line.func_code.co_varnames})

在 Python 3 中,应该用 __code__ 来代替 func_code。所以这个函数会是:

def skit(*lines, **kwargs):
    for line in lines:
        line(**{key: value for key, value in kwargs.iteritems() 
                if key in line.__code__.co_varnames})

另外可以参考: 你能列出一个 Python 函数接收的关键字参数吗?

撰写回答