pythonic方式做N次而没有索引变量?

Man*_*áoz 144 python for-loop coding-style

每天我都越来越喜欢python.

今天,我写了一些代码,如:

for i in xrange(N):
    do_something()
Run Code Online (Sandbox Code Playgroud)

我不得不做N次.但每次都不依赖于i(索引变量)的值.我意识到我正在创建一个我从未使用过的变量(i),并且我认为"在没有这个无用的索引变量的情况下,确实存在更多的pythonic方式."

所以......问题是:你知道如何以更多(pythonic)美丽的方式完成这个简单的任务吗?

Ale*_*lli 102

比循环更快的方法xrange(N)是:

import itertools

for _ in itertools.repeat(None, N):
    do_something()
Run Code Online (Sandbox Code Playgroud)

  • @Hamish:我用2.6测试的速度提高了32%(23.2 us vs 17.6 us,N = 1000).但无论如何,那真的是时间.我会默认使用OP的代码,因为它更容易读取(对我来说). (13认同)
  • 你确定速度真的相关吗?不是这样,如果你在那个循环中做了任何重要的事情,它很可能会花费数百或数千倍的时间作为你选择的迭代风格吗? (4认同)
  • 快多少?Python 3.1 中还有区别吗? (3认同)
  • 知道速度很好.我当然赞同迈克关于OP的代码更具可读性的观点. (3认同)

Gre*_*att 52

正如我在问这个问题时所学到的那样使用_变量,例如:

# A long way to do integer exponentiation
num = 2
power = 3
product = 1
for _ in xrange(power):
    product *= num
print product
Run Code Online (Sandbox Code Playgroud)

  • 不是downvoter,但可能是因为你指的是另一篇文章而不是在答案中添加更多细节 (6认同)
  • @Downgoat:感谢您的反馈.也就是说,关于这个成语没有太多可说的.我在提到另一篇文章时的观点是指出搜索可能产生了答案.我觉得具有讽刺意味的是,这个问题有多次与另一个问题相同. (3认同)

L̲̳*_*̲̳̳ 34

我只是用for _ in range(n)它,它是直截了当的.它将在Python 2中为大量数据生成整个列表,但如果您使用的是Python 3则不是问题.


Kho*_*rak 9

_与x相同.然而,它是一个python习惯用法,用于表示您不打算使用的标识符.在python中,这些标识符不会像其他语言中的变量一样记忆或分配空间.这很容易忘记.它们只是指向对象的名称,在这种情况下是每次迭代时的整数.


Any*_*orn 9

既然功能是一等公民,你可以写小包装(来自Alex答案)

def repeat(f, N):
    for _ in itertools.repeat(None, N): f()
Run Code Online (Sandbox Code Playgroud)

那么你可以传递函数作为参数.


小智 5

假设您已将do_something定义为一个函数,并且您想执行N次。也许您可以尝试以下操作:

todos = [do_something] * N  
for doit in todos:  
    doit()
Run Code Online (Sandbox Code Playgroud)

  • 当然。我们不仅要调用该函数一百万次,还要分配一百万个项目的列表。如果 CPU 正在工作,那么内存不应该受到一点压力吗?答案不能被定性为绝对“没有用”(它显示了一种不同的、有效的方法)所以我不能投票,但我不同意并且我完全反对它。 (48认同)
  • @tzot 为什么是居高临下的语气?此人努力编写答案,现在可能不鼓励将来做出贡献。即使它有性能影响,它也是一个可行的选择,特别是如果 N 很小,性能/内存影响并不重要。 (2认同)

jap*_*aps 5

我发现各种答案确实很优雅(尤其是Alex Martelli的答案),但我想直接量化性能,因此我编写了以下脚本:

from itertools import repeat
N = 10000000

def payload(a):
    pass

def standard(N):
    for x in range(N):
        payload(None)

def underscore(N):
    for _ in range(N):
        payload(None)

def loopiter(N):
    for _ in repeat(None, N):
        payload(None)

def loopiter2(N):
    for _ in map(payload, repeat(None, N)):
        pass

if __name__ == '__main__':
    import timeit
    print("standard: ",timeit.timeit("standard({})".format(N),
        setup="from __main__ import standard", number=1))
    print("underscore: ",timeit.timeit("underscore({})".format(N),
        setup="from __main__ import underscore", number=1))
    print("loopiter: ",timeit.timeit("loopiter({})".format(N),
        setup="from __main__ import loopiter", number=1))
    print("loopiter2: ",timeit.timeit("loopiter2({})".format(N),
        setup="from __main__ import loopiter2", number=1))
Run Code Online (Sandbox Code Playgroud)

我还提出了另一种解决方案,该解决方案基于Martelli的解决方案,并用于map()调用有效负载函数。好吧,我有点作弊,因为我可以自由地使有效负载接受被丢弃的参数:我不知道是否有解决方法。但是,结果如下:

standard:  0.8398549720004667
underscore:  0.8413165839992871
loopiter:  0.7110594899968419
loopiter2:  0.5891903560004721
Run Code Online (Sandbox Code Playgroud)

因此使用map可以比loop标准提高30%,比Martelli的标准提高19%。