>>> 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
喔即可。为什么我们不能拥有美好的东西?
理解中的解包似乎很明显/ pythonic,但由于他们不愿意添加该特殊错误消息,因此有理由禁用它。那么,该语法的问题是什么?
答案 0 :(得分:18)
引用the Py-Dev mailing list thread in which this feature was accepted:
这样就可以理解了。 IIRC,在补丁开发过程中我们意识到
f(*x for x in xs)
足够模糊 我们决定不允许它 - 请注意f(x for x in xs)
已经某种特殊情况,因为如果它是唯一的参数,那么参数只能是“裸”的生成器表达式。同样的推理不适用于(以那种形式)列出,设置和词典理解 - 虽然f(x for x in xs)
在含义上与f((x for x in xs))
相同,但[x for x in xs]
与{{}不同1}}(这是一个元素的列表,元素是一个生成器 表达)
(强调我的)
我还看了一下这个功能的Python问题跟踪器。我发现了一个在实施过程中进行讨论的问题。帮助他们实现这一目标的消息序列从here开始,对GvR在msg234766中介绍的歧义进行了很好的概述。
在链接腐烂的恐惧中,我在这里附加(格式化)消息:
所以我认为这里的测试功能应该是:
[(x for x in xs)]
然后我们可以尝试这样的事情:
def f(*a, **k): print(list(a), list(k))
打印一个生成器对象,因为它被解释为一个生成器表达式的参数。
但现在让我们考虑一下:
f(x for x in ['ab', 'cd'])
我个人认为这相当于:
f(*x for x in ['ab', 'cd'])
IOW:
f(*'ab', *'cd')
PEP没有说清楚这里要做什么。现在的问题是,我们应该将
f('a', 'b', 'c', 'd')
这样的东西解释为生成器表达式的扩展形式,还是*x for x in ...
的扩展形式?我不知何故认为后者更有用,也更符合逻辑。我的理由是PEP支持
*arg
之类的内容,将f(*a, *b)
解释为为列表中的每个f(*x for x in xs)
执行*x
事情是合理的。 {1}}。
最后,如the Abstract section of the corresponding PEP所述,此功能并未完全排除:
此PEP不包括列表,集合和字典理解中的解包运算符,尽管未排除未来的提案。
所以,我们可能很快就会看到它(绝对不是3.6,但是:-)而且我希望我们这样做,它们看起来不错。
答案 1 :(得分:11)
这是PEP 448中的简要解释,它引入了解包概括:
此PEP的早期迭代允许在内部解包运算符 列表,集合和字典理解作为展平运算符 容器的迭代:
Private Sub Copy_Formula(Dest As Integer, iCustomer As Long) Sheets("INPUT").Cells(2, Dest).Copy Sheets("INPUT").Range(Cells(4, Dest), Cells(3 + iCustomer, Dest)) Application.CutCopyMode = False Calculate Sheets("INPUT").Range(Cells(4, Dest), Cells(3 + iCustomer, Dest)).Copy Sheets("INPUT").Range(Cells(4, Dest), Cells(3 + iCustomer, Dest)).Cells(1, 1).PasteSpecial _ Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks:=False, Transpose:=False Application.CutCopyMode = False End Sub
这引起了人们对可读性和温和性的强烈担忧 支持。为了不利于争议较少的方面 PEP的其余部分不接受这一点。
但是,这可能在未来发生变化:
此PEP不包括列表,集合和字典理解中的解包运算符,尽管未来的提案未被排除。