元组作为函数参数

时间:2019-06-07 17:01:59

标签: python python-3.x tuples python-internals

在python中(在代码块中)的tuple由逗号定义;括号不是必需的(在以下情况下)。所以这三个都是等效的:

a, b = 1, 2
a, b = (1, 2)
(a, b) = 1, 2

如果我定义一个函数

def f(a, b):
    print(a, b)

以这种方式调用将起作用:

f(2, 3)

这不会:

f((2, 3))
# TypeError: f() missing 1 required positional argument: 'b'

当元组是函数参数时,python如何区别元组?这里的括号是必须的(我明白为什么是为什么,我很高兴python这样工作!)。

我的问题是:当元组是函数参数时,python如何区别元组。

3 个答案:

答案 0 :(得分:5)

元组的行为就像一个不可变的列表。用括号标记它们的事实可能令人困惑,但这或多或少是一个巧合-这是因为括号用于对事物进行分组在一起并减少歧义。

调用函数时,没有提供元组。您正在提供论据。元组可以是一个参数,但只能是一个-它只是类型为tuple的变量。

您可以做的是将一个元组(或列表)扩展成一系列带有以下符号的参数:

tup = (2, 3)
f(*tup)
# expand the tuple (2,3) into a series of arguments 2, 3

除了用**代替*以外,您还可以使用字典来做到这一点:

my_dict = {"arg1": 1, "arg2": 2}
f(arg1=my_dict["arg1"], arg2=my_dict["arg2"])
f(**my_dict)   # these are equivalent

另一方面,函数可以接受任意数量的参数(类似于其他语言对printf()的调用方式)。例如:

def g(*args):
    print("I got this many arguments:", len(args))

在这里,如果执行type(args),则会得到tuple,如果执行type(*args),则会出错。这是因为在函数标头中,*的作用恰恰相反:它将给函数提供的参数打包到单个元组中,以便您可以使用它们。请考虑以下内容:

g(2, 3)  # 2 arguments, both integers
g((2, 3)) # 1 argument, a tuple
g(*(2, 3)) # 2 arguments, both integers

简而言之

  • 函数以接受任意数量参数的方式构建
  • ***运算符可以将元组/列表/字典的解包一方面作为参数,然后在包装另一端
  • 单个元组/列表/字典仅是单个变量。

答案 1 :(得分:3)

为方便起见,Python根据需要为赋值语句构造一个临时元组。因此,一旦三个赋值语句到达数据移动位置,它们就会完全相同。

函数调用不是赋值语句;这是参考映射。因此,语义是不同的。

如果您希望Python将元组拆成两个单独的参数,请使用*运算符:

f(*(2, 3))

答案 2 :(得分:3)

问题在于,parens用于Python中的多种不同功能-调用函数,创建元组(不是 just 重要的逗号,请参见空元组() ),以更改表达式中的评估优先级。

如果对它们的解释含糊不清(例如,您的示例f(2, 3)可能是带有两个参数的函数调用,或者是带有一个元组的一个参数的函数调用),则语言必须做出选择。 / p>

如果实现了Python解析器,以便将其解析为一个元组,则不可能有多个参数的函数。如果实现了Python解析器,以便将其解析为两个参数,那么在没有解析器的情况下就无法传递文字元组。

显然,第一个限制更大,因此选择了第二个。

另一个例子是具有 one 元素的元组-(1+2)是一个产生数字3的表达式,还是具有一个元素3的元组?在这里,如果是第二个,则不可能使用括号来表示表达式中的优先级((3+4)*53+(4*5))。因此,决定在1元素元组((3,))的第一个元素之后要求逗号。