相关阅读
Python专栏https://blog.csdn.net/weixin_45791458/category_12403403.html
调用就是附带可能为空的一系列参数来执行一个可调用对象 (例如函数),它的语法的BNF范式如下所示,有关BNF范式的规则,可以参考之前的文章。
call ::= primary "(" [argument_list [","] | comprehension] ")"
argument_list ::= positional_arguments ["," starred_and_keywords]["," keywords_arguments]| starred_and_keywords ["," keywords_arguments]| keywords_arguments
positional_arguments ::= positional_item ("," positional_item)*
positional_item ::= assignment_expression | "*" expression
starred_and_keywords ::= ("*" expression | keyword_item)("," "*" expression | "," keyword_item)*
keywords_arguments ::= (keyword_item | "**" expression)("," keyword_item | "," "**" expression)*
keyword_item ::= identifier "=" expression
其中,primary是原型,代表编程语言中最紧密绑定的操作,它的具体可以为几种形式,可以是一个简单的函数名标识符。原型必须求值为一个可调用对象(用户定义的函数,内置函数,内置对象的方法,类对象,类实例的方法以及任何具有 __call__()
方法的对象都是可调用对象)。 所有参数表达式将在尝试调用前被求值。
参数列表是用()包围的可选项,可以是argument_list也可以是一个生成器推导式。常用的是argument_list,它可以有三种情况:
第一种是位置实参列表,后面是可选的加*实参和关键词实参列表,最后是可选的加**实参和关键词实参列表。
第二种是加*实参和关键词实参列表,后面是可选的加**实参和关键词实参列表。
第三种是只有加**实参和关键词实参列表。
一个可选项为在位置和关键字参数后加上逗号而不影响语义。
如果存在关键字实参,它们会先通过以下操作被转换为位置实参。首先,为形式参数创建一个未填充空位的表。 如果有N个位置实参,则它们会被放入前N个空位。 然后,对于每个关键字实参,使用标识符来确定其对应的空位(如果标识符与第一个形式参数名相同则使用第一个空位,依此类推)。 如果空位已被填充,则会引发TypeError异常。否则,将实参值放入空位,进行填充(即使表达式为None,它也会填充空位)。当所有实际参数处理完毕时,尚未填充的空位将用来自函数定义的相应默认值来填充。(函数一旦被定义,其默认值就会被计算;因此,当列表或字典这类可变对象被用作默认值时将会被所有未指定相应空位参数值的调用所共享;这种情况通常应当被避免。)如果任何一个未填充空位没有指定默认值,则会引发TypeError异常。在其他情况下,已填充空位的列表会被作为调用的形式参数列表。
如果任何关键字实参没有与之对应的形式参数名称,将会引发TypeError异常,除非有一个形式参数使用了**expression句法,该形式参数将接受一个包含了多余关键字实参的字典(使用关键字作为键而参数值作为与键对应的值),如果没有多余关键字实参,则它为一个(新的)空字典。
如果函数调用中出现了*expression句法,expression必须求值为一个的迭代类型。 来自该可迭代对象的元素会被当作解析为位置实参。 对于f(x1, x2, *y, x3, x4)调用,如果y求值为一个序列y1, y2, ..., ym,则它就等价于一个带有M+4个位置参数f(x1, x2, *y, x3, x4)的调用。
这样做的一个后果是虽然*expression句法可能出现于显式的关键字实参之后,但它会在关键字参数(以及任何**expression参数 -- 见下文)之前被处理为位置实参。 因此:
def f(a, b):print(a, b)f(b=1, *(2,)) # 一般情况下,位置参数不能在关键词参数后,但由*中解析的位置参数除外
输出:2 1 # 2会被解包并作为位置实参填充形参af(a=1, *(2,)) # 2被解包并作为位置实参填充形参a,之后关键词实参a=1又填充了a,因此报错
输出:Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: f() got multiple values for keyword argument 'a'f(1, *(2,))
输出:1 2