• Python:函数调用的实参


    相关阅读

    Python专栏icon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/category_12403403.html


            调用就是附带可能为空的一系列参数来执行一个可调用对象 (例如函数),它的语法的BNF范式如下所示,有关BNF范式的规则,可以参考之前的文章。

    1. call ::= primary "(" [argument_list [","] | comprehension] ")"
    2. argument_list ::= positional_arguments ["," starred_and_keywords]
    3. ["," keywords_arguments]
    4. | starred_and_keywords ["," keywords_arguments]
    5. | keywords_arguments
    6. positional_arguments ::= positional_item ("," positional_item)*
    7. positional_item ::= assignment_expression | "*" expression
    8. starred_and_keywords ::= ("*" expression | keyword_item)
    9. ("," "*" expression | "," keyword_item)*
    10. keywords_arguments ::= (keyword_item | "**" expression)
    11. ("," keyword_item | "," "**" expression)*
    12. 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参数 -- 见下文)之前被处理为位置实参。 因此:

    1. def f(a, b):
    2. print(a, b)
    3. f(b=1, *(2,)) # 一般情况下,位置参数不能在关键词参数后,但由*中解析的位置参数除外
    4. 输出:2 1 # 2会被解包并作为位置实参填充形参a
    5. f(a=1, *(2,)) # 2被解包并作为位置实参填充形参a,之后关键词实参a=1又填充了a,因此报错
    6. 输出:Traceback (most recent call last):
    7. File "", line 1, in <module>
    8. TypeError: f() got multiple values for keyword argument 'a'
    9. f(1, *(2,))
    10. 输出:1 2

            下面的文章还介绍了函数定义的形参相关问题,欢迎浏览。

    Python:函数定义的形参icon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/article/details/132889428?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22132889428%22%2C%22source%22%3A%22weixin_45791458%22%7D

  • 相关阅读:
    使用del语句删除名称对引用计数的影响
    Vue官方文档(42):函数式组件的定义和使用
    响应的结构与Http常见状态码
    地磁场与磁力计
    【高等数学基础进阶】常微分方程-补充 & 多元函数微分学-补充
    GitOps 介绍
    Linux常用命令及项目部署
    dp,优化记录,打扑克
    MyBatis 环境搭建
    javaWeb监听器Listener -自定义监听器类实现(二)
  • 原文地址:https://blog.csdn.net/weixin_45791458/article/details/132912878