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

问题:在python中使用参数列表调用函数

我正在尝试在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])

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

I’m trying to call a function inside another function in python, but can’t find the right syntax. What I want to do is something like this:

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])

In this case first call will work, and second won’t. What I want to modify is the wrapper function and not the called functions.


回答 0

为了扩大其他答案:

在该行中:

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]

To expand a little on the other answers:

In the line:

def wrapper(func, *args):

The * next to args means “take the rest of the parameters given and put them in a list called args“.

In the line:

    func(*args)

The * next to args here means “take this list called args and ‘unwrap’ it into the rest of the parameters.

So you can do the following:

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])

In wrapper2, the list is passed explicitly, but in both wrappers args contains the list [1,2,3].


回答 1

包装函数的最简单方法

    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

The simpliest way to wrap a function

    func(*args, **kwargs)

… is to manually write a wrapper that would call func() inside itself:

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

In Python function is an object, so you can pass it’s name as an argument of another function and return it. You can also write a wrapper generator for any function anyFunc():

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

Please also note that in Python when you don’t know or don’t want to name all the arguments of a function, you can refer to a tuple of arguments, which is denoted by its name, preceded by an asterisk in the parentheses after the function name:

    *args

For example you can define a function that would take any number of arguments:

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

Python provides for even further manipulation on function arguments. You can allow a function to take keyword arguments. Within the function body the keyword arguments are held in a dictionary. In the parentheses after the function name this dictionary is denoted by two asterisks followed by the name of the dictionary:

    **kwargs

A similar example that prints the keyword arguments dictionary:

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

回答 2

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

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

并来自官方python教程

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

You can use *args and **kwargs syntax for variable length arguments.

What do *args and **kwargs mean?

And from the official python tutorial

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


回答 3

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

func(args)

阅读

func(*args)

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

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

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

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

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

The literal answer to your question (to do exactly what you asked, changing only the wrapper, not the functions or the function calls) is simply to alter the line

func(args)

to read

func(*args)

This tells Python to take the list given (in this case, args) and pass its contents to the function as positional arguments.

This trick works on both “sides” of the function call, so a function defined like this:

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

would be able to accept as many positional arguments as you throw at it, and place them all into a list called args.

I hope this helps to clarify things a little. Note that this is all possible with dicts/keyword arguments as well, using ** instead of *.


回答 4

您需要使用参数解包..

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)

You need to use arguments unpacking..

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)

回答 5

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

这里是一个小的代码段,它结合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中断言等长

A small addition to previous answers, since I couldn’t find a solution for a problem, which is not worth opening a new question, but led me here.

Here is a small code snippet, which combines lists, zip() and *args, to provide a wrapper that can deal with an unknown amount of functions with an unknown amount of arguments.

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)

Keep in mind, that zip() does not provide a safety check for lists of unequal length, see zip iterators asserting for equal length in python.