Every day I love python more and more.
每天我都越来越喜欢python。
Today, I was writing some code like:
今天,我写了一些代码,比如:
for i in xrange(N):
do_something()
I had to do something N times. But each time didn't depend on the value of i
(index variable). I realized that I was creating a variable I never used (i
), and I thought "There surely is a more pythonic way of doing this without the need for that useless index variable."
我要做N次。但每次都不依赖于i (index变量)的值。我意识到我在创建一个我从未使用过的变量(I),我认为“在不需要那个无用的索引变量的情况下,这样做肯定会有更多的python方法。”
So... the question is: do you know how to do this simple task in a more (pythonic) beautiful way?
所以…问题是:你知道如何用(毕达哥拉斯的)更漂亮的方式完成这个简单的任务吗?
8 个解决方案
#1
81
A slightly faster approach than looping on xrange(N)
is:
比在xrange(N)上循环快一点的方法是:
import itertools
for _ in itertools.repeat(None, N):
do_something()
#2
42
Use the _ variable, as I learned when I asked this question, for example:
使用_变量,就像我问这个问题时学到的,例如:
# A long way to do integer exponentiation
num = 2
power = 3
product = 1
for _ in xrange(power):
product *= num
print product
#3
26
I just use for _ in range(n)
, it's straight to the point. It's going to generate the entire list for huge numbers in Python 2, but if you're using Python 3 it's not a problem.
我只是用在范围(n)中的_,它直接指向一点。它会在Python 2中生成大量的列表,但是如果你使用的是Python 3,这不是问题。
#4
7
since function is first-class citizen, you can write small wrapper (from Alex answers)
由于函数是一等公民,您可以编写小包装(来自Alex answers)
def repeat(f, N):
for _ in itertools.repeat(None, N): f()
then you can pass function as argument.
然后可以将函数作为参数传递。
#5
7
The _ is the same thing as x. However it's a python idiom that's used to indicate an identifier that you don't intend to use. In python these identifiers don't takes memor or allocate space like variables do in other languages. It's easy to forget that. They're just names that point to objects, in this case an integer on each iteration.
_和x是一样的,但是它是一个python习语,用来表示您不打算使用的标识符。在python中,这些标识符不像其他语言中的变量那样使用memor或分配空间。很容易忘记这一点。它们只是指向对象的名称,在这种情况下,每个迭代都是一个整数。
#6
5
Assume that you've defined do_something as a function, and you'd like to perform it N times. Maybe you can try the following:
假设您已经将do_something定义为一个函数,并且希望执行N次。也许你可以试试下面的方法:
todos = [do_something] * N
for doit in todos:
doit()
#7
1
What about a simple while loop?
简单的while循环怎么样?
while times > 0:
do_something()
times -= 1
You already have the variable; why not use it?
你已经有了变量;为什么不使用它呢?
#8
1
I found the various answers really elegant (especially Alex Martelli's) but I wanted to quantify performance first hand, so I cooked up the following script:
我发现各种各样的答案都非常优雅(尤其是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))
I also came up with an alternative solution that builds on Martelli's one and uses map()
to call the payload function. OK, I cheated a bit in that I took the freedom of making the payload accept a parameter that gets discarded: I don't know if there is a way around this. Nevertheless, here are the results:
我还提出了一种替代方案,该方案构建在Martelli的方案之上,并使用map()调用有效负载函数。好吧,我做了一点弊,我*地让有效载荷接受一个被丢弃的参数:我不知道是否有办法解决这个问题。然而,结果如下:
standard: 0.8398549720004667
underscore: 0.8413165839992871
loopiter: 0.7110594899968419
loopiter2: 0.5891903560004721
so using map yields an improvement of approximately 30% over the standard for loop and an extra 19% over Martelli's.
因此,使用map可以比loop的标准提高大约30%,比Martelli的标准提高19%。
#1
81
A slightly faster approach than looping on xrange(N)
is:
比在xrange(N)上循环快一点的方法是:
import itertools
for _ in itertools.repeat(None, N):
do_something()
#2
42
Use the _ variable, as I learned when I asked this question, for example:
使用_变量,就像我问这个问题时学到的,例如:
# A long way to do integer exponentiation
num = 2
power = 3
product = 1
for _ in xrange(power):
product *= num
print product
#3
26
I just use for _ in range(n)
, it's straight to the point. It's going to generate the entire list for huge numbers in Python 2, but if you're using Python 3 it's not a problem.
我只是用在范围(n)中的_,它直接指向一点。它会在Python 2中生成大量的列表,但是如果你使用的是Python 3,这不是问题。
#4
7
since function is first-class citizen, you can write small wrapper (from Alex answers)
由于函数是一等公民,您可以编写小包装(来自Alex answers)
def repeat(f, N):
for _ in itertools.repeat(None, N): f()
then you can pass function as argument.
然后可以将函数作为参数传递。
#5
7
The _ is the same thing as x. However it's a python idiom that's used to indicate an identifier that you don't intend to use. In python these identifiers don't takes memor or allocate space like variables do in other languages. It's easy to forget that. They're just names that point to objects, in this case an integer on each iteration.
_和x是一样的,但是它是一个python习语,用来表示您不打算使用的标识符。在python中,这些标识符不像其他语言中的变量那样使用memor或分配空间。很容易忘记这一点。它们只是指向对象的名称,在这种情况下,每个迭代都是一个整数。
#6
5
Assume that you've defined do_something as a function, and you'd like to perform it N times. Maybe you can try the following:
假设您已经将do_something定义为一个函数,并且希望执行N次。也许你可以试试下面的方法:
todos = [do_something] * N
for doit in todos:
doit()
#7
1
What about a simple while loop?
简单的while循环怎么样?
while times > 0:
do_something()
times -= 1
You already have the variable; why not use it?
你已经有了变量;为什么不使用它呢?
#8
1
I found the various answers really elegant (especially Alex Martelli's) but I wanted to quantify performance first hand, so I cooked up the following script:
我发现各种各样的答案都非常优雅(尤其是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))
I also came up with an alternative solution that builds on Martelli's one and uses map()
to call the payload function. OK, I cheated a bit in that I took the freedom of making the payload accept a parameter that gets discarded: I don't know if there is a way around this. Nevertheless, here are the results:
我还提出了一种替代方案,该方案构建在Martelli的方案之上,并使用map()调用有效负载函数。好吧,我做了一点弊,我*地让有效载荷接受一个被丢弃的参数:我不知道是否有办法解决这个问题。然而,结果如下:
standard: 0.8398549720004667
underscore: 0.8413165839992871
loopiter: 0.7110594899968419
loopiter2: 0.5891903560004721
so using map yields an improvement of approximately 30% over the standard for loop and an extra 19% over Martelli's.
因此,使用map可以比loop的标准提高大约30%,比Martelli的标准提高19%。