Python—为什么我的列表在传递给带有varargs(仅关键字)的方法时会变成元组

Python—为什么我的列表在传递给带有varargs(仅关键字)的方法时会变成元组,python,python-3.x,variadic-functions,Python,Python 3.x,Variadic Functions,我将一个列表传递给一个接受多个参数(*值)的方法。如果我传递了多个以“,”分隔的值,这一切都很好,但是如果我传递了一个列表,那么*值会变成一个元组,并且不会迭代值,唯一的元素就是我想要迭代的列表。有人能解释一下吗?有什么方法可以解决这个问题吗?两种方法都有效吗 我的方法: def accept(*values): for value in values: #do something with value 作品: foo.accept(value

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

我的方法:

    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。任意参数列表

最后,使用频率最低的选项是指定可以使用任意数量的参数调用函数,即使用*args。这些参数将封装在一个元组中

另一点可能有助于我们理解的是,在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)
或:


是的,我想避免对我的列表进行额外的包装,总是重复这些项目(例如value1、value2、value3),直到mgilson提出解决方案,我才找到解决方案。我不知道你能打开这张单子。
foo.accept(*[1, 2, 3])