毎日pythonが大好きです。
今日、私は次のようなコードを書いていました。
for i in xrange(N):
do_something()
私は何回かしなければなりませんでした。しかし、毎回i
(インデックス変数)の値に依存しませんでした。使用したことのない変数(i
)を作成していることに気付き、「その役に立たないインデックス変数を必要とせずに、もっとPython的な方法が確実にある」と考えました。
質問は次のとおりです。この単純なタスクをより(Pythonの)美しい方法で行う方法を知っていますか?
xrange(N)
でループするよりも少し速い方法は次のとおりです。
import itertools
for _ in itertools.repeat(None, N):
do_something()
これを尋ねたときに学んだように、_変数を使用します question 、たとえば:
# A long way to do integer exponentiation
num = 2
power = 3
product = 1
for _ in xrange(power):
product *= num
print product
私はfor _ in range(n)
を使用していますが、それは要点にまっすぐです。 Python 2の膨大な数のリスト全体を生成しますが、Python 3を使用している場合は問題ありません。
_はxと同じものです。ただし、使用するつもりのない識別子を示すために使用されるpythonイディオムです。 pythonでは、これらの識別子は他の言語の変数のように覚えたりスペースを割り当てたりしません。忘れがちです。それらはオブジェクトを指す単なる名前であり、この場合は各反復の整数です。
関数はファーストクラスの市民なので、小さなラッパーを書くことができます(Alexの回答から)
def repeat(f, N):
for _ in itertools.repeat(None, N): f()
関数を引数として渡すことができます。
さまざまな回答が非常にエレガントであることがわかりました(特に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 __== '__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))
また、Martelliのソリューションに基づいて、map()
を使用してペイロード関数を呼び出す代替ソリューションを思い付きました。 OK、ペイロードが破棄されるパラメーターを受け入れるようにするという自由を選んだという点で、私は少しごまかしました。これを回避する方法があるかどうかはわかりません。それにもかかわらず、結果は次のとおりです。
standard: 0.8398549720004667
underscore: 0.8413165839992871
loopiter: 0.7110594899968419
loopiter2: 0.5891903560004721
したがって、mapを使用すると、標準forループよりも約30%、Martelliの場合よりもさらに19%改善されます。
do_somethingを関数として定義し、それをN回実行したいとします。たぶん、あなたは以下を試すことができます:
todos = [do_something] * N
for doit in todos:
doit()
単純なwhileループはどうですか?
while times > 0:
do_something()
times -= 1
すでに変数があります。なぜそれを使用しないのですか?