在python中使用参数列表调用函数


150

我正在尝试在python中的另一个函数内调用一个函数,但是找不到正确的语法。我想做的是这样的:

def wrapper(func, args):
    func(args)

def func1(x):
    print(x)

def func2(x, y, z):
    return x+y+z

wrapper(func1, [x])
wrapper(func2, [x, y, z])

在这种情况下,第一个呼叫将起作用,而第二个则将不起作用。我要修改的是包装函数,而不是被调用的函数。

Answers:


268

为了扩大其他答案:

在该行中:

def wrapper(func, *args):

*旁边的* args表示“使用给出的其余参数并将它们放在一个称为args” 的列表中。

在该行中:

    func(*args)

args此处旁边的* 表示“将该列表称为args,并将其“解包”到其余参数中。

因此,您可以执行以下操作:

def wrapper1(func, *args): # with star
    func(*args)

def wrapper2(func, args): # without star
    func(*args)

def func2(x, y, z):
    print x+y+z

wrapper1(func2, 1, 2, 3)
wrapper2(func2, [1, 2, 3])

在中wrapper2,列表是显式传递的,但是在两个包装器中都args包含list [1,2,3]


26
我没有发现经常提到的一件事是如何使用* args调用函数,如果您有要传递的列表或元组。为此,您需要这样称呼它:wrapper1(func2,* mylist)
阿里2010年

* args in def wrapper(func, *args)method(params object[] args)C#中的内容。
Jim Aho

1
请注意,它*args必须是函数定义中的最后一个参数。
Jim Aho

2
The * next to args means "take the rest of the parameters given and put them in a list called args".它把它们放在一个元组中,而不是一个列表中。
TomaszNocoń16年

20

包装函数的最简单方法

    func(*args, **kwargs)

...是手动编写一个包装,该包装将在其内部调用func()

    def wrapper(*args, **kwargs):
        # do something before
        try:
            return func(*a, **kwargs)
        finally:
            # do something after

在Python中,函数是一个对象,因此您可以将其名称作为另一个函数的参数传递并返回它。您还可以为任何函数anyFunc()编写包装器生成器:

    def wrapperGenerator(anyFunc, *args, **kwargs):
        def wrapper(*args, **kwargs):
            try:
                # do something before
                return anyFunc(*args, **kwargs)
            finally:
                #do something after
        return wrapper

另请注意,在Python中,当您不知道或不想命名函数的所有参数时,可以引用参数元组,以其名称表示,并在括号后加星号函数名称:

    *args

例如,您可以定义一个可以接受任意数量参数的函数:

    def testFunc(*args):
        print args    # prints the tuple of arguments

Python提供了对函数参数的进一步操作。您可以允许函数接受关键字参数。在函数体内,关键字参数保存在字典中。在函数名称后的括号中,此字典用两个星号表示,后面是字典的名称:

    **kwargs

一个类似的示例显示关键字参数字典:

    def testFunc(**kwargs):
        print kwargs    # prints the dictionary of keyword arguments

11

您可以对可变长度参数使用* args和** kwargs语法。

* args和** kwargs是什么意思?

并来自官方python教程

http://docs.python.org/dev/tutorial/controlflow.html#more-on-defining-functions


所以我需要它同时获取* args和** kwargs并与它们一起调用吗?
SurDin

1
不,您可以使用“ /”或“ /”,但它们通常配对在一起。就您而言,您只需要* args。
2009年

好的,它可以工作,但是仍然不能让我传递参数列表,我必须分别传递它们。在我目前的情况下,这并不会给我带来太大的麻烦,但是知道如何做到这一点仍然会很好。(我需要做wrapper(func2,x,y,z)而不是wrapper(func2,[x,y,z])))
SurDin

如果要使用后者,则在包装器调用func2时使用* args形式,但不要在“ def包装器”中使用。
亚历克斯·马丁里

10

问题的字面答案(完全按照您的要求做,只更改包装器,而不更改函数或函数调用)只是为了改变行

func(args)

阅读

func(*args)

这告诉Python接受给定的列表(在本例中为args),并将其内容作为位置参数传递给函数。

这个技巧在函数调用的两个方面都起作用,因此定义的函数如下:

def func2(*args):
    return sum(args)

将能够接受与您抛出的一样多的位置参数,并将它们全部放入名为的列表中args

我希望这有助于澄清一些事情。请注意,使用dicts // keywords参数也可以使用**代替*


8

您需要使用参数解包..

def wrapper(func, *args):
    func(*args)

def func1(x):
    print(x)

def func2(x, y, z):
    print x+y+z

wrapper(func1, 1)
wrapper(func2, 1, 2, 3)

0

对以前的答案进行了少量补充,因为我找不到问题的解决方案,这不值得提出一个新问题,而是将我引到了这里。

这里是一个小的代码段,它结合listszip()并且*args,以提供一个包装能够处理的功能与参数未知量的未知量。

def f1(var1, var2, var3):
    print(var1+var2+var3)

def f2(var1, var2):
    print(var1*var2)

def f3():
    print('f3, empty')

def wrapper(a,b, func_list, arg_list):
    print(a)
    for f,var in zip(func_list,arg_list):
        f(*var)
    print(b)

f_list = [f1, f2, f3]
a_list = [[1,2,3], [4,5], []]

wrapper('begin', 'end', f_list, a_list)

请记住,这zip()不能为不等长列表提供安全检查,请参阅zip迭代器在python中断言等长

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.