способ сделать что-то N раз без индексной переменной? - PullRequest
135 голосов
/ 04 июня 2010

Каждый день я люблю питона все больше и больше.

Сегодня я писал код вроде:

for i in xrange(N):
    do_something()

Я должен был что-то сделать N раз. Но каждый раз не зависел от значения i (индексная переменная). Я понял, что создаю переменную, которую никогда не использовал (i), и подумал: «Конечно, есть более питонический способ сделать это без необходимости этой бесполезной индексной переменной».

Итак ... вопрос в том, знаете ли вы, как сделать это простое задание более (питонически) красивым способом?

Ответы [ 8 ]

99 голосов
/ 04 июня 2010

Немного более быстрый подход, чем зацикливание на xrange(N):

import itertools

for _ in itertools.repeat(None, N):
    do_something()
48 голосов
/ 04 июня 2010

Используйте переменную _, как я узнал, когда задавал этот вопрос , например:

# A long way to do integer exponentiation
num = 2
power = 3
product = 1
for _ in xrange(power):
    product *= num
print product
33 голосов

Я просто использую for _ in range(n), это прямо к делу. В Python 2 будет сформирован весь список для огромных чисел, но если вы используете Python 3, это не проблема.

9 голосов
/ 04 июня 2010

, поскольку функция является гражданином первого класса, вы можете написать небольшую оболочку (из ответов Алекса)

def repeat(f, N):
    for _ in itertools.repeat(None, N): f()

, а затем передать функцию в качестве аргумента.

9 голосов
/ 04 июня 2010

_ - это то же самое, что и x. Однако это идиома Python, которая используется для обозначения идентификатора, который вы не собираетесь использовать. В python эти идентификаторы не запоминаются и не выделяют место, как переменные в других языках. Это легко забыть. Это просто имена, которые указывают на объекты, в данном случае целое число на каждой итерации.

4 голосов
/ 12 апреля 2018

Я нашел различные ответы очень элегантными (особенно ответы Алекса Мартелли), но я хотел измерить производительность из первых рук, поэтому я подготовил следующий сценарий:

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

, поэтому использование карты дает улучшение примерно на 30% по сравнению со стандартным циклом for и на 19% больше, чем у Мартелли.

4 голосов
/ 04 июня 2010

Предположим, что вы определили do_something как функцию, и вы хотите выполнить ее N раз. Может быть, вы можете попробовать следующее:

todos = [do_something] * N  
for doit in todos:  
    doit()
0 голосов
/ 02 февраля 2012

А как насчет простого цикла while?

while times > 0:
    do_something()
    times -= 1

У вас уже есть переменная; почему бы не использовать его?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...