加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – 函数调用和varagrs

发布时间:2020-12-20 11:37:22 所属栏目:Python 来源:网络整理
导读:def func(a,b,c,d):print(a,d) func(1,c=3,*(2,),**{'d':4})func(1,2,**{'d':4}) 为什么前者呼叫工作但后者不工作?我的意思是不应该第一次返回错误?不*只是解压缩一个iterable? 解决方法 正如 the docs所说: If the syntax *expression appears in the
def func(a,b,c,d):print(a,d)

func(1,c=3,*(2,),**{'d':4})
func(1,2,**{'d':4})

为什么前者呼叫工作但后者不工作?我的意思是不应该第一次返回错误?不*只是解压缩一个iterable?

解决方法

正如 the docs所说:

If the syntax *expression appears in the function call,expression must evaluate to an iterable. Elements from this iterable are treated as if they were additional positional arguments; if there are positional arguments x1,…,xN,and expression evaluates to a sequence y1,yM,this is equivalent to a call with M+N positional arguments x1,xN,y1,yM.

A consequence of this is that although the *expression syntax may appear after some keyword arguments,it is processed before the keyword arguments…

许多人对功能定义具有类似的,有时是误导性相似的语法这一事实感到困惑.

在函数定义中,变量参数参数(如* args)位于任何仅关键字参数之前.当然,仅限关键字并且具有默认值是完全独立的,但是仅关键字参数都具有默认值是很常见的.所以,语法通常看起来像def func(a,* args,c = 4,** kwargs):.这可能会让你期望func(1,c = 3,** {‘d’:4}成为匹配的调用语法,即使它不是.只记得def func(a = 1,** kwargs)是完全合法的,它仍然是一个位置或关键字参数和ca关键字参数.

如果你对CPython中它的工作原理感兴趣(尽管其他实现可能都非常相似):

函数调用本身被编译为传递堆栈上表达式的值,仍然与普通参数分开.它位于解释器内部,在函数调用求值程序中,函数体执行的堆栈框架被构建,其中该值被分解为额外的参数.

查看CPython如何解析和编译此代码可能会有所帮助:

>>> astpp(ast.parse("func(1,**{'d':4})"))
Module(
  body=[
    Expr(
      value=Call(
        func=Name(id='func',ctx=Load()),args=[Num(n=1)],keywords=[keyword(arg='c',value=Num(n=3))],starargs=Tuple(elts=[Num(n=2)],kwargs=Dict(keys=[Str(s='d')],values=[Num(n=4)])))])"

即使您不理解AST,您也应该能够看到(2,)在解析时仍然是独立的,存储在名为starargs的字段中.

这会被编译为这个字节码:

2           0 LOAD_GLOBAL              0 (func)
              3 LOAD_CONST               1 (1)
              6 LOAD_CONST               2 ('c')
              9 LOAD_CONST               3 (3)
             12 LOAD_CONST               7 ((2,))
             15 BUILD_MAP                1
             18 LOAD_CONST               5 (4)
             21 LOAD_CONST               6 ('d')
             24 STORE_MAP
             25 CALL_FUNCTION_VAR_KW   257
             28 POP_TOP
             29 LOAD_CONST               0 (None)
             32 RETURN_VALUE

你可能不明白所有那些胡言乱语,但是你可以看到元组(2,)正在偏移12处被加载到堆栈上,并且当操作码CALL_FUNCTION_VAR_KW被执行时它仍然在堆栈上.您可以在文档中查看操作码,其中说:

Calls a function. argc is interpreted as in CALL_FUNCTION. The top element on the stack contains the keyword arguments dictionary,followed by the variable-arguments tuple,followed by explicit keyword and positional arguments.

因此,“变量参数元组”仍然是分开的.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读