解开概括 [英] Unpacking generalizations
问题描述
>>> LOL = [[1, 2], ['three']]
>>> [*LOL[0], *LOL[1]]
[1, 2, 'three']
好的!再见 itertools.chain
.无论如何,从没喜欢过你.
Alright! Goodbye itertools.chain
. Never liked you much anyway.
>>> [*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
哦.为什么我们不能拥有美好的事物?
Oh. Why can't we have nice things?
解压缩似乎是很明显的/Python式的,但是由于他们不愿意添加该特殊错误消息,因此有理由将其禁用.那么,该语法有什么问题?
Unpacking in a comprehension seems to be obvious/pythonic, but since they've bothered to add that special error message there was a reason for disabling it. So, what's the problem with that syntax?
推荐答案
这样就可以产生理解力了. 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]
与[(x for x in xs)]
不同(这是一个列表)一个元素,而该元素是一个生成器 表达式)
So that leaves comprehensions. IIRC, during the development of the patch we realized that
f(*x for x in xs)
is sufficiently ambiguous that we decided to disallow it -- note thatf(x for x in xs)
is already somewhat of a special case because an argument can only be a "bare" generator expression if it is the only argument. The same reasoning doesn't apply (in that form) to list, set and dict comprehensions -- whilef(x for x in xs)
is identical in meaning tof((x for x in xs))
,[x for x in xs]
is NOT the same as[(x for x in xs)]
(that's a list of one element, and the element is a generator expression)
(强调我的)
我还窥视了该功能的Python问题跟踪器.我发现一个问题,在实施过程中进行了讨论. 此处的一系列信息帮助他们实现了这一目标,并很好地介绍了歧义在 msg234766 中由GvR提出.
I also took a peek at the Python issue tracker for this feature. I found an issue in which discussion took place while implementing it. The sequence of messages that helped them come to this realization starts here with a nice overview of the ambiguity introduced presented in msg234766 by GvR.
在link-rot的 fear 中,我在此处附加(格式化的)消息:
In fear of link-rot, I'm attaching the (formatted) message here:
所以我认为这里的测试功能应该是:
So I think the test function here should be:
def f(*a, **k): print(list(a), list(k))
然后我们可以尝试以下操作:
Then we can try things like:
f(x for x in ['ab', 'cd'])
打印一个生成器对象,因为它被解释为一个生成器表达式的参数.
which prints a generator object, because this is interpreted as an argument that's a generator expression.
但是现在让我们考虑:
f(*x for x in ['ab', 'cd'])
我个人希望这等同于:
f(*'ab', *'cd')
IOW:
f('a', 'b', 'c', 'd')
PEP在此没有明确说明要做什么.现在的问题是,我们应该将诸如*x for x in ...
之类的内容解释为生成器表达式的扩展形式,还是作为*arg
的扩展形式?我不知何故认为后者更有用,而且逻辑扩展也更合理.
The PEP doesn't give clarity on what to do here. The question now is, should we interpret things like *x for x in ...
as an extended form of generator expression, or as an extended form of *arg
? I somehow think the latter is more useful and also the more logical extension.
我的理由是PEP支持f(*a, *b)
之类的东西,并且将f(*x for x in xs)
解释为对列表xs
中的每个x
做*x
事情是很合逻辑的.
My reasoning is that the PEP supports things like f(*a, *b)
and it would be fairly logical to interpret f(*x for x in xs)
as doing the *x
thing for each x
in the list xs
.
最后,如相应PEP的摘要部分,但并未完全排除此功能:
Finally, as noted in the Abstract section of the corresponding PEP, this feature isn't completely ruled out:
此PEP并未在列表,集合和字典理解中包括解包运算符,尽管尚未将其排除在以后的建议之内.
因此,我们可能很快就会看到它(虽然不是:-,绝对不是3.6,),但我希望我们这样做,它们看起来不错.
So, we might get to see it sometime soon (definitely not 3.6, though :-) and I hope we do, they look nice.
这篇关于解开概括的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!