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

Python 拆包:[x,y],(x,y),x,y-有什么区别?,python,iterable-unpacking,Python,Iterable Unpacking,在Python中,用[]解压函数调用、用()解压函数调用或不解压函数调用之间有什么区别 def(): 返回0,1 a、 b=f()#1 [a,b]=f()#2 (a,b)=f()#3 没有区别。无论使用哪种语法序列,都会生成相同的字节码 >>> def f(): ... return 0, 1 ... >>> import dis >>> dis.dis('[a,b] = f()') 1 0 LOAD_NAME

在Python中,用
[]
解压函数调用、用
()
解压函数调用或不解压函数调用之间有什么区别

def():
返回0,1
a、 b=f()#1
[a,b]=f()#2
(a,b)=f()#3

没有区别。无论使用哪种语法序列,都会生成相同的字节码

>>> 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
在每种情况下,只需调用
f
,然后使用
UNPACK\u SEQUENCE
生成要分配给
a
b
的值


即使你想说字节码是CPython的一个实现细节,链式赋值的定义也不是。给定

意思与

tmp = f()
x = tmp
[a, b] = tmp
x
分配的是
f()
(一个元组)的结果,而不是“列表”
[a,b]


最后,这里是赋值语句的语法:

assignment_stmt ::=  (target_list "=")+ (starred_expression | yield_expression)
target_list     ::=  target ("," target)* [","]
target          ::=  identifier
                     | "(" [target_list] ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | slicing
                     | "*" target

可以说,
“[”[target_list]“]”
可以而且应该在Python3中删除。现在很难实现这样一个突破性的更改,因为声明倾向于避免将来对Python进行任何2到3转换的更改。

正如另一个答案所解释的,没有语义上的差异。喜欢一种形式胜过另一种形式的唯一原因是视觉清晰度
x,y=f()
通常比较整洁,但有时可能会编写类似于
[(id,)]=do\u sql\u query()
的内容,以指示结果应该是一个包含元组的列表。赋值目标
[(id,)]
在语义上等同于
(id,),
,但它向人类读者传达了更多信息。

没有任何区别。如果您需要更具说服力的话,可以使用
dis
模块来分解包含每个版本的函数,并观察它们的字节码是否相同。您唯一能找到的参考是您是否调用了type(thing)。\uuu name\uu不确定它是否是重复的,肯定相关:@reece没有任何东西可以调用
type
;这里的括号纯粹是语法上的
[a,b]=f()
不会在此处创建任何类型的列表。在这种情况下,所有列表都是冗余的。但是括号对于解包嵌套的东西是有用的:
a,(b,c)=[0,1],[2,3]
导致
a=[0,1]
b=2
c=3
。另外,我相信赋值操作符的定义:=/code>排除了任何类似
(x:=[a,b])=f()的技巧。(这至少是一个语法错误。)
assignment_stmt ::=  (target_list "=")+ (starred_expression | yield_expression)
target_list     ::=  target ("," target)* [","]
target          ::=  identifier
                     | "(" [target_list] ")"
                     | "[" [target_list] "]"
                     | attributeref
                     | subscription
                     | slicing
                     | "*" target