这出现在a recent PyCon talk。
声明
[] = []
没有任何意义,但它也不会引发异常。我觉得这一定是因为拆包规则。您也可以使用列表tuple unpacking,例如,
[a, b] = [1, 2]
做你期望的事。作为逻辑结果,当解包的元素数为0时,这也应该有效,这可以解释为什么分配给空列表是有效的。当您尝试将非空列表分配给空列表时会发生什么,这进一步支持了这一理论:
>>> [] = [1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
如果元组也是如此,我会对这个解释感到满意。如果我们可以解压缩到包含0个元素的列表,我们也应该能够解包为具有0个元素的元组,不是吗?但是:
>>> () = ()
File "<stdin>", line 1
SyntaxError: can't assign to ()
似乎解包规则不适用于元组,因为它们用于列表。我想不出对这种不一致的任何解释。这种行为有原因吗?
答案 0 :(得分:20)
@ user2357112的评论似乎是巧合似乎是正确的。 Python源代码的相关部分位于Python/ast.c
:
switch (e->kind) {
# several cases snipped
case List_kind:
e->v.List.ctx = ctx;
s = e->v.List.elts;
break;
case Tuple_kind:
if (asdl_seq_LEN(e->v.Tuple.elts)) {
e->v.Tuple.ctx = ctx;
s = e->v.Tuple.elts;
}
else {
expr_name = "()";
}
break;
# several more cases snipped
}
/* Check for error string set by switch */
if (expr_name) {
char buf[300];
PyOS_snprintf(buf, sizeof(buf),
"can't %s %s",
ctx == Store ? "assign to" : "delete",
expr_name);
return ast_error(c, n, buf);
}
tuple
明确检查长度不为零并在出现错误时引发错误。 list
没有任何此类检查,因此没有例外。
我没有看到任何特殊原因允许在分配给空元组时出现错误,因此允许分配到空列表中,但也许有一些特殊情况我不考虑。我建议这可能是一个(微不足道的)错误,并且两种类型的行为都应该相同。
答案 1 :(得分:12)
当我绊倒好奇的东西时,我决定尝试使用dis
弄清楚这里发生了什么:
>>> def foo():
... [] = []
...
>>> dis.dis(foo)
2 0 BUILD_LIST 0
3 UNPACK_SEQUENCE 0
6 LOAD_CONST 0 (None)
9 RETURN_VALUE
>>> def bar():
... () = ()
...
File "<stdin>", line 2
SyntaxError: can't assign to ()
不知何故,Python 编译器特殊情况下LHS上的空元组。这种差异与the specification不同,后者指出:
将对象分配给单个目标按递归方式定义如下。
...
- 如果目标是括在括号中或方括号中的目标列表:对象必须是一个可迭代的项目数与目标列表中的目标相同,并且其项目从左到右分配,到相应的目标。
所以看起来你在CPython中发现了一个合法的,但最终无关紧要的错误(2.7.8和3.4.1测试过)。
IronPython 2.6.1表现出相同的区别,但是Jython 2.7b3 +有一个陌生人的行为,() = ()
开始声明似乎无法结束它。
答案 2 :(得分:3)
“分配到列表”是错误的思考方式。
在所有情况下,你都是解包:Python解释器从三种方式创建一个解包指令来编写它,左侧没有列表或元组(代码由{{代码提供) 3}}):
>>> def f():
... iterable = [1, 2]
... a, b = iterable
... (c, d) = iterable
... [e, f] = iterable
...
>>> from dis import dis
>>> dis(f)
2 0 LOAD_CONST 1 (1)
3 LOAD_CONST 2 (2)
6 BUILD_LIST 2
9 STORE_FAST 0 (iterable)
3 12 LOAD_FAST 0 (iterable)
15 UNPACK_SEQUENCE 2
18 STORE_FAST 1 (a)
21 STORE_FAST 2 (b)
4 24 LOAD_FAST 0 (iterable)
27 UNPACK_SEQUENCE 2
30 STORE_FAST 3 (c)
33 STORE_FAST 4 (d)
5 36 LOAD_FAST 0 (iterable)
39 UNPACK_SEQUENCE 2
42 STORE_FAST 5 (e)
45 STORE_FAST 6 (f)
48 LOAD_CONST 0 (None)
51 RETURN_VALUE
如您所见,所有三种陈述完全相同。
现在解压缩的基本原理是:
_iterator = iter(some_iterable)
a = next(_iterator)
b = next(_iterator)
for superfluous_element in _iterator:
# this only happens if there’s something left
raise SyntaxError('Expected some_iterable to have 2 elements')
类似地,左侧有更多或更少的名字。
现在正如@blckknght所说:编译器由于某种原因检查左侧是否为空元组并且不允许,但是如果它是空列表则不会。
允许分配0个名称是唯一且合乎逻辑的:为什么不呢?你基本上只断言右边的iterable是空的。这种观点似乎也出现在/u/old-man-prismo @gecko提到的共识中:让我们允许() = iterable
。