raf*_*foo 28 python iterable-unpacking
在 Python 中使用[]、使用()或不使用任何方式解包函数调用有什么区别?
def f():
return 0, 1
a, b = f() # 1
[a, b] = f() # 2
(a, b) = f() # 3
Run Code Online (Sandbox Code Playgroud)
che*_*ner 34
没有区别。无论您使用哪种句法序列,都会生成相同的字节码。
>>> def f():
... return 0, 1
...
>>> import dis
>>> dis.dis('[a,b] = f()')
1 0 LOAD_NAME 0 (f)
2 CALL_FUNCTION 0
4 UNPACK_SEQUENCE 2
6 STORE_NAME 1 (a)
8 STORE_NAME 2 (b)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
>>> dis.dis('(a,b) = f()')
1 0 LOAD_NAME 0 (f)
2 CALL_FUNCTION 0
4 UNPACK_SEQUENCE 2
6 STORE_NAME 1 (a)
8 STORE_NAME 2 (b)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
>>> dis.dis('a, b = f()')
1 0 LOAD_NAME 0 (f)
2 CALL_FUNCTION 0
4 UNPACK_SEQUENCE 2
6 STORE_NAME 1 (a)
8 STORE_NAME 2 (b)
10 LOAD_CONST 0 (None)
12 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
在每种情况下,您只需调用f,然后使用UNPACK_SEQUENCE生成要分配给a和的值b。
即使您想争论字节码是 CPython 的实现细节,链式赋值的定义也不是. 给定的
x = [a, b] = f()
Run Code Online (Sandbox Code Playgroud)
意思是一样的
tmp = f()
x = tmp
[a, b] = tmp
Run Code Online (Sandbox Code Playgroud)
x被分配f()(a tuple)的结果,而不是 "list" [a, b]。
最后,这是赋值语句的语法:
assignment_stmt ::= (target_list "=")+ (starred_expression | yield_expression)
target_list ::= target ("," target)* [","]
target ::= identifier
| "(" [target_list] ")"
| "[" [target_list] "]"
| attributeref
| subscription
| slicing
| "*" target
Run Code Online (Sandbox Code Playgroud)
可以说,"[" [target_list] "]"Python 3 中本来可以也应该删除 。这种重大更改现在很难实现,因为已声明避免将来在 2 到 3 转换的规模上对 Python 进行任何更改。
正如另一个答案所解释的那样,没有语义差异。偏爱一种形式而不是另一种形式的唯一原因是视觉清晰度;x, y = f()通常更简洁,但[(id,)] = do_sql_query()有时可能会写类似的东西来表明结果应该是一个包含元组的列表。分配目标[(id,)]在语义上等同于,(id,),但它向人类读者传达了更多信息。
| 归档时间: |
|
| 查看次数: |
1371 次 |
| 最近记录: |