如何将列表理解与非理解项目混合?
我想从一些单独的项目以及由列表理解定义的项目组构建一个列表。假设我想要一个 list ['foo', 0, 2, 4, 'bar'],0,2,4从哪里来的理解。我知道的唯一方法是:
['foo'] + [x*2 for x in range(3)] + ['bar']
有没有办法在没有明确附加的情况下做到这一点?我正在寻找一些与以下非工作所需语法等效的巧妙方法:
['foo', x*2 for x in range(3), 'bar'] # invalid syntax :(
我的假设是,当使用显式+运算符时,类似的语法可能会避免创建所有中间临时列表,然后必须逐个复制这些中间临时列表,以便将它们附加到正在构建的列表中。
对于 Python 2.7 和 3.x,我正在寻找一种最好是 Pythonic(惯用语)的解决方案 - 如果它们不同的话。
激励代码如下,ScreamingBOM命名元组在哪里- 我正在尝试构建元组,同时创建尽可能少的临时变量,因为其中一些可能变得相当大。
def make_screaming_bom(self, bom):
return ScreamingBOM(
summary = [
['', '', 'generated on: %s' % bom.time],
['', bom.unique_parts, 'unique parts'],
[]
]
+ [['', count, 'total %s' % (type)] for type, count in bom.counts.items()]
+ [
['', bom.total, 'total placements'],
[],
['BOM: %s' % (bom.title)],
['Assembly Part Number/Revision: %s / %s' % (bom.basename, bom.revision)],
['Customer: %s' % (bom.company)]
],
# other tuple fields follow
)
回答
避免临时性的最好方法是使用带有生成器表达式的广义解包:
['foo', *(x*2 for x in range(3)), 'bar']
在 CPython 3.9 上,它编译为等效于创建一个空列表的代码,appending 'foo',extending 与geneexpr,然后appending 'bar'。该extend步骤消耗了生成器而没有意识到它作为 a list,避免了任何临时性。带有临时的代码list(请参阅bb1 的回答)可能会稍微快一些,但是如果您打算避免使用临时代码,那么这是内存效率最高的解决方案。
Python 2“解决方案”是您只需list手动append和extend逐行制作一个,直到完成。如果你真的坚持单行,无论多么丑陋, usingitertools.chain将允许一些非常类似于广义解包在 3.8 中首次引入时的工作方式(未解包的项目被包装在临时tuples 中,然后 alist是通过解包所有参数构建的通过):
list(itertools.chain(('foo',), (x*2 for x in range(3)), ('bar',)))
但是 Python 2 已经停产一年多了,所以只需编写现代 Python 3 代码即可。:-)
- @1313e: Yeah, Python 2 is dead, so I don't really care about it. Some ugly code with `itertools.chain` is possible there if they *really* insist, but it's awful, not worth the trouble.