如何将列表理解与非理解项目混合?

我想从一些单独的项目以及由列表理解定义的项目组构建一个列表。假设我想要一个 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手动appendextend逐行制作一个,直到完成。如果你真的坚持单行,无论多么丑陋, 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.

以上是如何将列表理解与非理解项目混合?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>