python – 函数调用和varagrs
def func(a,b,c,d):print(a,d)
func(1,c=3,*(2,),**{'d':4}) func(1,2,**{'d':4}) 为什么前者呼叫工作但后者不工作?我的意思是不应该第一次返回错误?不*只是解压缩一个iterable? 解决方法
正如
the docs所说:
许多人对功能定义具有类似的,有时是误导性相似的语法这一事实感到困惑. 在函数定义中,变量参数参数(如* 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处被加载到堆栈上,并且当操作码
因此,“变量参数元组”仍然是分开的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |