Python 循环 vs 列表推导 vs map的副作用(即不使用返回值)

2 投票
2 回答
1676 浏览
提问于 2025-04-17 14:21

简而言之:哪个更好?

1.- [r.update(r.pop('some_key')) for r in res if r.get('some_key')]

2.- map(lambda r: r.update(r.pop('some_key') if r.get('some_key') else []), res)

3.- map(lambda r: r.update(r.pop('some_key')), filter(lambda r: r.get('some_key'), res))

4.- for r in res:
        if r.get('some_key'):
            for element in r['some_key']:
                r[element] = r['some_key'][element]
            del r['some_key']

5.- Insert your own approach here

注意:这段代码不是用在生产环境中的,而是用在测试中,所以我更关心代码的可读性和可维护性,而不是性能。不过,我也想知道,如果这是生产代码,关于哪个更好的选择(在性能和可读性之间的权衡)是否会有所不同。因为'some_key'的元素数量很少,如果这有影响的话。

背景:我读过一篇文章,讨论了Python的列表推导和map函数,其中的一个被接受的回答说:

[...] 在其他情况下,列表推导可能更快,而且大多数(不是全部)Python爱好者认为它们更直接、更清晰 [...].

然而,另一个问题的被接受回答仅仅为了副作用使用列表推导是否符合Python风格?中提到:

这样做非常不符合Python风格 [仅仅为了副作用使用列表推导,忽略返回值],任何有经验的Python爱好者都会对此表示不满。中间生成的列表在创建后就被丢弃了,而且它可能会非常非常大,因此创建它的成本可能很高。

附言:我已经有了自己认为哪个更好的看法,但我的一个同事不同意。这就是我询问的原因。

2 个回答

2
1.- [r.update(r.pop('some_key')) for r in res if r.get('some_key')]

使用列表推导式来产生副作用是不推荐的。因为它会创建一个列表,但最后这个列表会被丢弃。

2.- map(lambda r: r.update(r.pop('some_key') if r.get('some_key') else []), res)

1差不多,只是这个在Python 3.X中会出问题。

3.- map(lambda r: r.update(r.pop('some_key')), filter(lambda r: r.get('some_key'), res))

3更糟。除了使用map并依赖副作用外,你还增加了函数调用的开销。

4.- for r in res:
        if r.get('some_key'):
            for element in r['some_key']:
                r[element] = r['some_key'][element]
            del r['some_key']

这个比其他的都好。

  1. 没有生成不必要的列表,这些列表最后会被丢掉。
  2. 在Python 3.x中可以正常工作。
  3. 没有额外的函数调用开销。

5.- 在这里插入你自己的方法。

    for r in res:
        if 'some_key' in r:
            r.update(r['some_key'])
            del r['some_key']
2

我觉得这个对Abhijit回答的变种,同时也是我第四点的变种,是最好的选择。

for r in res:
    r.update(r.pop('some_key', {}))
  • 拥有普通for循环的所有优点
  • 容易理解
  • 只需要两行代码
  • 不需要if条件语句

撰写回答