假设我有一个列表l = [1,2,3]
,我想在该列表中创建一组所有数字及其正方形。理想情况下,在单个理解表达式中。
我能想到的最好的是(列表中的两次迭代):
set(_ for _ in l).union(_ * _ for _ in l)
假设我有一个列表l = [1,2,3]
,我想在该列表中创建一组所有数字及其正方形。理想情况下,在单个理解表达式中。
我能想到的最好的是(列表中的两次迭代):
set(_ for _ in l).union(_ * _ for _ in l)
您自己的代码可以缩短为:
set(l).union(x**2 for x in l)
在其中我重命名_
为x
,因为_
表明该值不重要,但它是。
严格来说,你仍然在迭代list
两次,但第一次是隐式的。
如果你坚持迭代一次,你会得到这个:
{y for x in l for y in (x, x**2)}
这是一种双重理解,包括以下内容:
result = set()
for x in l:
for y in (x, x**2):
result.add(y)
IMO,set(l + [i ** 2 for i in l])
是一个更好的解决方案。它比嵌套生成器理解更清晰。
我做了一个基准测试:
import timeit
l = list(range(5))
print(timeit.timeit("set(l + [_ ** 2 for _ in l])", 'from __main__ import ' + ', '.join(globals())))
print(timeit.timeit("{y for x in l for y in (x, x**2)}", 'from __main__ import ' + ', '.join(globals())))
输出:
3.0309128219996637
3.1958301850008866
它显示set(l + [i ** 2 for i in l])
有点快。我认为的原因是嵌套生成器理解需要(x, x**2)
为每个循环创建内部对象,这使得它变慢。
import timeit
l = list(range(200000))
print(timeit.timeit("set(l + [_ ** 2 for _ in l])", 'from __main__ import ' + ', '.join(globals()), number=100))
print(timeit.timeit("{y for x in l for y in (x, x**2)}", 'from __main__ import ' + ', '.join(globals()), number=100))
输出:
16.46792753900081
19.72252997099895