Python - 为什么我的列表在将它传递给带有可变参数的方法时变成了一个元组(仅限关键字)

Python - Why is my list turning into a tuple when passing it to a method with varargs (keywordonly)

我将一个列表传递给一个接受多个参数(*值)的方法。如果我传递多个由“”分隔的值,一切都很好,但如果我传递一个列表,*值会变成一个元组并且不会迭代这些值,唯一的元素是我想要迭代的列表。有人可以解释一下吗?有没有办法解决这个问题,两种方法都有效?

我的方法:

    def accept(*values): 
        for value in values:
            #do something with value

作品:

foo.accept(value1, value2, value3)

无效:

values = [value1, value2, value3]
foo.accept(values)

感谢您的帮助

您需要使用 * 运算符在函数调用中解压缩列表:

foo.accept(*values)

python 中的多个参数功能的工作原理是,您可以将可变数量的参数传递给函数,它会自动将它们变成一个列表(因此您不必手动) 然后执行函数中的代码。因此,当您执行 foo.accept(value1, value2, value3) 时,它会创建一个列表 [value1, value2, value3] 并将此列表标记为函数的参数,然后您的代码将遍历该列表。然而,当你

values = [value1, value2, value3]
foo.accept(values)

可变参数 (varargs) 功能会将您的值列表包装到另一个列表中,因此现在您的函数的参数是 [[value1, value2, value3]] 并且当您的 for 循环进行迭代时,它只会遍历其中的一个元素这个更大的列表(一个元素是您的值列表)。

希望对您有所帮助!

此语法明确用于将任意数量的参数作为输入

def accept1(*values): 
    #do something with values

对于任何给定数量的参数,它与写入完全相同,例如:

def accept2(arg1, arg2, arg3):
    values = (arg1, arg2, arg3)
    #do something with values

要调用带有 3 个参数的函数,您可以像往常一样为这两个参数编写:

accept1(1,2,3)
accept2(1,2,3)

但是如果你在列表或元组中有参数,你可以这样做

args = (1,2,3)
accept1(args[0], args[1], args[3])
accept2(args[0], args[1], args[3])

这当然是不灵活的,而且要写很多所以 python 有一个快捷方式再次适用于任意数量的参数:

accept1(*args)
accept2(*args)

所以在这两种情况下,* 表示通过

处理多个参数的通用方法
  • 将函数的各个参数打包到列表中(在 def 中),或者
  • 将列表解包为函数的各个参数。

来自 Python 2.7.10 文档(略作编辑):

4.7.3. Arbitrary Argument Lists

Finally, the least frequently used option is to specify that a function can be called with an arbitrary number of arguments, i.e. using *args. These arguments will be wrapped up in a tuple.

另一点可能有助于我们理解的是,在 Python 中,括号在以下代码行中是多余的:

a = (1, 2, 3)

写就够了:

a = 1, 2, 3

所以开始回答问题。当你有 foo.accept(1, 2, 3) 时,变量参数被包装到一个元组中。使用你最喜欢的调试器通过代码验证这一步到 accept() 并发现参数确实被包装在一个元组中:

values = (1, 2, 3)

这是定义所期望的,迭代遍历元组 1、2 和 3 的三个元素。

另一方面,当您再次调用 foo.accept([1, 2, 3]) 时,根据定义,参数被包装在一个元组中。通过代码进入accept()来验证这一步,发现:

values = ([1, 2, 3])

这可能出乎意料,但这是传递 *args 的方式。现在迭代遍历元组 [1, 2, 3].

中的一个元素

变通方法通常针对要实现的目标。但也许像这样简单:

foo.accept(1, 2, 3)

或:

foo.accept(*[1, 2, 3])