1

假设我有一个列表l = [1,2,3],我想在该列表中创建一组所有数字及其正方形。理想情况下,在单个理解表达式中。

我能想到的最好的是(列表中的两次迭代):

set(_ for _ in l).union(_ * _ for _ in l)
4

2 回答 2

3

您自己的代码可以缩短为:

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)
于 2017-12-14T03:21:19.303 回答
0

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
于 2017-12-14T04:00:22.830 回答