拆包:[x,y], (x,y), x,y - 有什么区别?

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 进行任何更改。


kay*_*ya3 8

正如另一个答案所解释的那样,没有语义差异。偏爱一种形式而不是另一种形式的唯一原因是视觉清晰度;x, y = f()通常更简洁,但[(id,)] = do_sql_query()有时可能会写类似的东西来表明结果应该是一个包含元组的列表。分配目标[(id,)]在语义上等同于,(id,),但它向人类读者传达了更多信息。