Я нашел различные ответы действительно элегантными (особенно ответы Алекса Мартелли), но я хотел оценить производительность из первых рук, поэтому приготовил следующий сценарий:
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))
Я также придумал альтернативное решение, основанное на решении Мартелли и использующее map() для вызова функции полезной нагрузки. Хорошо, я немного обманул, позволив полезной нагрузке принимать параметр, который отбрасывается: я не знаю, есть ли способ обойти это. Тем не менее, вот результаты:
standard: 0.8398549720004667
underscore: 0.8413165839992871
loopiter: 0.7110594899968419
loopiter2: 0.5891903560004721
Таким образом, использование map дает улучшение примерно на 30% по сравнению со стандартным циклом for и на 19% больше, чем у Мартелли.
person
japs
schedule
12.04.2018
range. - person John Henckel   schedule 07.12.2016