为什么不给空列表(例如 =“”)分配一个错误?
在Python 3.4中,我打字
[] = ""  它工作正常,没有例外引发。 虽然[]当然不等于"" 。 
 [] = () 
也工作正常。
 "" = [] 
如预期的那样引发了一个例外,
 () = "" 
如预期的那样引发了一个例外。 发生什么了?
你没有比较平等。 你正在分配 。
Python允许你分配给多个目标:
 foo, bar = 1, 2 
 将这两个值分别赋值给foo和bar 。 所有你需要的是右边的一个序列或者可迭代的 ,左边的名字列表或元组。 
当你这样做时:
 [] = "" 
您为空的名称列表分配了一个空序列(空string仍是序列)。
这和本质上是一样的:
 [foo, bar, baz] = "abc" 
 你最终得到foo = "a" , bar = "b"和baz = "c" ,但是用更less的字符。 
 但是,您不能将其分配给string,因此分配左侧的""从不起作用,并且始终是语法错误。 
请参阅作业语句文档 :
赋值语句评估expression式列表(请记住,这可以是单个expression式或逗号分隔列表,后者产生一个元组),并将单个结果对象从左到右分配给每个目标列表。
和
将对象分配给目标列表( 可选地包含在圆括号或方括号中)recursion地定义如下。
强调我的 。
  Python不会为空列表抛出语法错误实际上是一个错误! 正式logging的语法不允许有空的目标列表,对于空()你会得到一个错误。 见bug 23275 ; 它被认为是一个无害的bug: 
起点是认识到这已经很长时间了,是无害的。
另请参阅为什么它是有效的分配给一个空的列表,而不是一个空的元组?
它遵循文档中的Assignment语句部分规则,
assignment_stmt ::= (target_list "=")+ (expression_list | yield_expression)如果
target list是以逗号分隔的目标列表: 对象必须是与目标列表中的目标相同数目的项目,并且项目从左到右分配给相应的目标。对象必须是与目标列表中的目标相同数量的项目,并且项目从左到右分配给相应的目标。
所以,当你说
 [] = "" 
  ""是一个可迭代的(任何有效的pythonstring都是可迭代的),它被解压到列表的元素上。 
例如,
 >>> [a, b, c] = "123" >>> a, b, c ('1', '2', '3') 
既然你有一个空的string和一个空的列表,没有什么可以解压的。 所以,没有错误。
但是,试试这个
 >>> [] = "1" Traceback (most recent call last): File "<input>", line 1, in <module> ValueError: too many values to unpack (expected 0) >>> [a] = "" Traceback (most recent call last): File "<input>", line 1, in <module> ValueError: need more than 0 values to unpack 
 在[] = "1"情况下,您试图在空的variables列表上解压string"1" 。 所以它抱怨“太多的值解包(预期0)”。 
 同样的方式,在[a] = ""情况下,你有一个空string,所以没有真正的解压缩,但你打开一个variables,这是不可能的。 这就是为什么它抱怨“需要超过0个值才能解包”。 
除此之外,正如你注意到的那样,
 >>> [] = () 
 也抛出没有错误,因为()是一个空的元组。 
 >>> () () >>> type(()) <class 'tuple'> 
当它被解压到一个空的列表上时,没有任何东西需要解压。 所以没有错误。
但是,当你这样做
 >>> "" = [] File "<input>", line 1 SyntaxError: can't assign to literal >>> "" = () File "<input>", line 1 SyntaxError: can't assign to literal 
如错误消息所示,您正试图分配给string文字。 这是不可能的。 这就是为什么你得到错误。 这就像是在说
 >>> 1 = "one" File "<input>", line 1 SyntaxError: can't assign to literal 
内幕
 在内部,这个赋值操作将被转换为UNPACK_SEQUENCE操作码, 
 >>> dis(compile('[] = ""', "string", "exec")) 1 0 LOAD_CONST 0 ('') 3 UNPACK_SEQUENCE 0 6 LOAD_CONST 1 (None) 
 在这里,由于string是空的, UNPACK_SEQUENCE解包0次。 但是,当你有这样的事情 
 >>> dis(compile('[a, b, c] = "123"', "string", "exec")) 1 0 LOAD_CONST 0 ('123') 3 UNPACK_SEQUENCE 3 6 STORE_NAME 0 (a) 9 STORE_NAME 1 (b) 12 STORE_NAME 2 (c) 15 LOAD_CONST 1 (None) 18 RETURN_VALUE 
 序列123从右到左被解压到堆栈中。 所以,堆栈的顶部将是1 ,下一个将是2 ,最后是3 。 然后从堆栈顶部逐个指定左侧expression式的variables。 
顺便说一下,在Python中,这是如何在同一expression式中执行多个赋值的。 例如,
 a, b, c, d, e, f = u, v, w, x, y, z 
这是有效的,因为右手的值被用来构造一个元组,然后它将被解压到左边的值。
 >>> dis(compile('a, b, c, d, e, f = u, v, w, x, y, z', "string", "exec")) 1 0 LOAD_NAME 0 (u) 3 LOAD_NAME 1 (v) 6 LOAD_NAME 2 (w) 9 LOAD_NAME 3 (x) 12 LOAD_NAME 4 (y) 15 LOAD_NAME 5 (z) 18 BUILD_TUPLE 6 21 UNPACK_SEQUENCE 6 24 STORE_NAME 6 (a) 27 STORE_NAME 7 (b) 30 STORE_NAME 8 (c) 33 STORE_NAME 9 (d) 36 STORE_NAME 10 (e) 39 STORE_NAME 11 (f) 42 LOAD_CONST 0 (None) 45 RETURN_VALUE 
 但是经典的交换技术a, b = b, a使用了堆栈顶部元素的旋转。 如果你只有两个或三个元素,那么它们将被特殊的ROT_TWO和ROT_THREE指令处理,而不是构造元组ROT_THREE包。 
 >>> dis(compile('a, b = b, a', "string", "exec")) 1 0 LOAD_NAME 0 (b) 3 LOAD_NAME 1 (a) 6 ROT_TWO 7 STORE_NAME 1 (a) 10 STORE_NAME 0 (b) 13 LOAD_CONST 0 (None) 16 RETURN_VALUE