使用列表推导式构建元组

91

我该如何使用列表推导式从一个列表构建一个2元组的元组。它应该等价于:

tup = ()
for element in alist:
    tup = tup + ((element.foo, element.bar),)
3个回答

132
tup = tuple((element.foo, element.bar) for element in alist)

从技术上讲,这是一个生成器表达式。它类似于列表推导式,但是惰性地求值,不需要为中间列表分配内存。

为了完整起见,列表推导式将如下所示:

tup = tuple([(element.foo, element.bar) for element in alist])

 

PS:attrgetter 不一定更快(这里 alist 有一百万个元素):

In [37]: %timeit tuple([(element.foo, element.bar) for element in alist])
1 loops, best of 3: 165 ms per loop

In [38]: %timeit tuple((element.foo, element.bar) for element in alist)
10 loops, best of 3: 155 ms per loop

In [39]: %timeit tuple(map(operator.attrgetter('foo','bar'), alist))
1 loops, best of 3: 283 ms per loop

In [40]: getter = operator.attrgetter('foo','bar')

In [41]: %timeit tuple(map(getter, alist))
1 loops, best of 3: 284 ms per loop

In [46]: %timeit tuple(imap(getter, alist))
1 loops, best of 3: 264 ms per loop

1
(+1) 可能值得指出的是,从技术上讲,这不是一个列表推导式(但我相信 OP 不会介意 :)) - NPE
3
你还可以使用 tuple(map(operator.attrgetter('foo','bar'),alist)) 进行操作。为了可读性,我可能会使用您发布的那个,但是 attrgetter 可能具有轻微的性能优势。如果在实际紧密循环中,请使用 timeit 测试一下。 - mgilson
2
在这个例子中,列表推导和生成器表达式的区别是什么,因为它上面调用了tuple()?不管使用哪种形式,它不会占用相同的内存空间吗? - Octipi
2
将生成器表达式传递给元组构造函数的效果是评估整个生成器表达式,并使用与列表推导相同的内存。在我的机器上,列表推导运行速度约快20%。如果逐个使用术语,则可以看到使用生成器的好处,但是当传递给元组构造函数时,我看不到任何优势。 - Octipi
3
不,它使用的内存是原来的两倍。首先,它消耗生成器中的所有元素以构建一个列表,然后从列表创建一个元组。此时,生成器产生的元素集有两个副本,并且只有在一段时间之后才会垃圾回收列表。如果生成器很大,则可能无法同时在内存中保留列表和元组,即使对于一条指令也是如此。由于你正在用函数调用加属性查找来替换属性查找,所以可以预期attrgetter会减慢速度。 - Bakuriu
显示剩余10条评论

3

尽管已经有可行的答案:

tup = tuple((element.foo, element.bar) for element in alist)

最短的方法是:(逗号必须在末尾!):

tup = *((elements.foo, elements.bar) for elements in alist),

哪种解决方案更易读或更符合Python的编程风格是有争议的。

*(...)的解释: *(...),


-2
您可以使用以下表达式。
tup = *[(element.foo, element.bar) for element in alist]

这将首先生成一个元组列表,然后将该元组列表转换为元组的元组。


1
你忘记添加尾随逗号了。如果没有它,你会得到一个错误 tup = *[(element.foo, element.bar) for element in alist], - Roman Kazakov
1
在我的看法中,使用列表并不是非常好的选择。如果在末尾添加逗号,则无需使用列表,就可以起到相同的作用,就像 @RomanKazakov 提到的那样。 - tturbo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接