j0k*_*ker 30 python iterable-unpacking
这是在最近的PyCon演讲中提出的.
该声明
[] = []
Run Code Online (Sandbox Code Playgroud)
没有任何意义,但它也没有抛出异常.我觉得这一定是因为拆包规则.您也可以使用列表进行元组拆包,例如,
[a, b] = [1, 2]
Run Code Online (Sandbox Code Playgroud)
做你所期望的.作为逻辑结果,当解包的元素数为0时,这也应该有效,这可以解释为什么分配给空列表是有效的.当您尝试将非空列表分配给空列表时会发生什么,这进一步支持了这一理论:
>>> [] = [1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
Run Code Online (Sandbox Code Playgroud)
如果对于元组也是如此,我会对这个解释感到满意.如果我们可以解压缩到包含0个元素的列表,我们也应该能够解包为具有0个元素的元组,不是吗?然而:
>>> () = ()
File "<stdin>", line 1
SyntaxError: can't assign to ()
Run Code Online (Sandbox Code Playgroud)
似乎解包规则不适用于元组,因为它们用于列表.我想不出对这种不一致的任何解释.这种行为有原因吗?
Blc*_*ght 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);
}
Run Code Online (Sandbox Code Playgroud)
tuples有一个明确的检查,长度不是零,并在它出现时引发错误.list没有任何这样的检查,所以没有例外.
当分配给空元组是一个错误时,我没有看到允许赋值给空列表的任何特殊原因,但也许有一些我不考虑的特殊情况.我建议这可能是一个(微不足道的)错误,并且这两种类型的行为应该是相同的.
Ign*_*ams 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 ()
Run Code Online (Sandbox Code Playgroud)
不知何故,Python 编译器特殊情况下LHS上的空元组.这种差异因规格而异,其中规定:
如下递归地定义对象到单个目标的分配.
...
- 如果目标是括在括号中或方括号中的目标列表:对象必须是与目标列表中的目标具有相同数量的项目的可迭代对象,并且其项目从左到右分配给相应的目标.
所以看起来你已经在CPython中找到了一个合法的,虽然最终无关紧要的错误(2.7.8和3.4.1测试).
IronPython 2.6.1表现出相同的区别,但是Jython 2.7b3 +有一个陌生人的行为,() = ()开始一个看似无法结束它的声明.
| 归档时间: |
|
| 查看次数: |
1324 次 |
| 最近记录: |