解开概括
>>> LOL = [[1, 2], ['three']]
>>> [*LOL[0], *LOL[1]]
[1, 2, 'three']
好的!再见itertools.chain
。从来没有喜欢过你。
>>> [*L for L in LOL]
File "<ipython-input-21-e86d2c09c33f>", line 1
[*L for L in LOL]
^
SyntaxError: iterable unpacking cannot be used in comprehension
呵呵 。为什么我们不能拥有美好的事物?
不幸的是,所有这些语法都有错误:
[*l for l in lists] # for l in lists: result.extend(l)
{*s for s in sets} # for s in sets: result.update(s)
{**d for d in dicts} # for d in dicts: result.update(d)
(*g for g in gens) # for g in gens: yield from g
理解力的解压缩似乎很明显并且是Python式的,并且从速记“ for-loop&append”到“ for-loop&extend”有相当自然的扩展。
但是,由于他们不愿意添加该特殊错误消息,因此大概有一个禁用它的原因。那么,该语法有什么问题?
-
这是 简单 的解释PEP
448其中介绍了拆包的概括:此PEP的早期迭代允许将列表,集合和字典理解内的操作符解包,作为对容器可迭代项的展平操作符:
>>> ranges = [range(i) for i in range(5)] >>> [*item for item in ranges] [0, 0, 1, 0, 1, 2, 0, 1, 2, 3] >>> {*item for item in ranges} {0, 1, 2, 3}
对可读性和轻度支持的强烈关注混合在一起。为了不使PEP争议较小的方面受到不利影响,提案的其余部分对此不予接受。
但是,将来可能会改变:
该PEP在列表,集合和字典理解中不包括解包运算符,尽管将来的提议并未排除。
PEP提到“对可读性的强烈关注”。我不了解整个故事,但是可以在邮件列表中找到导致此决定的详细讨论:
如果在列表理解中允许拆包概括,则这是一个不明确的示例:
[*t for t in [(1, 'a'), (2, 'b'), (3, 'c')]]
根据其中一位核心开发人员的说法,结果是
[1, 'a', 2, 'b', 3, 'c']
否定会令人惊讶[(1, 'a'), (2, 'b'), (3, 'c')]
。由于没有正式的共识,因此允许这些特殊情况更为简单。