Возможно ли реализовать цикл Python для диапазона без переменной итератора?

Можно ли сделать следующее без i?

for i in range(some_number):
    # do something

Если вы просто хотите сделать что-то N раз и не нуждаетесь в итераторе.

Ответ 1

Сверху моей головы нет.

Я думаю, что лучшее, что вы могли бы сделать, это что-то вроде этого:

def loop(f,n):
    for i in xrange(n): f()

loop(lambda: <insert expression here>, 5)

Но я думаю, что вы можете просто жить с дополнительной переменной i.

Здесь можно использовать переменную _, которая на самом деле является просто другой переменной.

for _ in range(n):
    do_something()

Обратите внимание, что _ присваивается последний результат, возвращаемый в интерактивном сеансе python:

>>> 1+2
3
>>> _
3

По этой причине я не буду использовать его таким образом. Я не знаю никакой идиомы, как упоминал Райан. Это может испортить ваш интерпретатор.

>>> for _ in xrange(10): pass
...
>>> _
9
>>> 1+2
3
>>> _
9

И согласно грамматике python, это приемлемое имя переменной:

идентификатор:: =              (буква | "_" ) (буква | цифра | "_" ) *

Ответ 2

Возможно, вы ищете

for _ in itertools.repeat(None, times): ...

это самый быстрый способ повторить итерацию times раз в Python.

Ответ 3

Общая идиома для назначения значения, которое не используется, - это имя _.

for _ in range(times):
    do_stuff()

Ответ 4

Все, кто предлагает вам использовать _, не говорит, что _ часто используется как ярлык для одного из gettext функции, поэтому, если вы хотите, чтобы ваше программное обеспечение было доступно на нескольких языках, вам лучше избегать использования его для других целей.

import gettext
gettext.bindtextdomain('myapplication', '/path/to/my/language/directory')
gettext.textdomain('myapplication')
_ = gettext.gettext
# ...
print _('This is a translatable string.')

Ответ 5

Здесь случайная идея, которая использует (злоупотребляет?) модель данных .

class Counter(object):
  def __init__(self, val):
    self.val = val

  def __nonzero__(self):
    self.val -= 1
    return self.val >= 0

x = Counter(5)
while x:
  # Do something
  pass

Интересно, есть ли что-то подобное в стандартных библиотеках?

Ответ 6

Вы можете использовать _11 (или любой номер или другой недопустимый идентификатор), чтобы предотвратить сопоставление имен с gettext. Каждый раз, когда вы используете символ underscore + invalid, вы получаете фиктивное имя, которое может использоваться в цикле for.

Ответ 7

Может быть, ответ будет зависеть от того, какая у вас проблема с использованием итератора? может использоваться

i = 100
while i:
    print i
    i-=1

или

def loop(N, doSomething):
    if not N:
        return
    print doSomething(N)
    loop(N-1, doSomething)

loop(100, lambda a:a)

но, откровенно говоря, я не вижу смысла использовать такие подходы

Ответ 8

t=0    
for _ in range (0, 10):
  print t
  t = t+1

ВЫВОД:
0 1 2 3 4 5 6 7 9

Ответ 9

Я вообще согласен с решениями, приведенными выше. А именно:

  • Использование подчеркивания в for -loop (2 и более строк)
  • Определение нормального счетчика while (3 и более строк)
  • Объявление пользовательского класса с реализацией __nonzero__ (еще много строк)

Если нужно определить объект, как в # 3, я бы рекомендовал реализовать протокол для с ключевым словом или применить contextlib.

Далее я предлагаю еще одно решение. Это 3 лайнера и не имеет высшей элегантности, но использует пакет itertools и, следовательно, может представлять интерес.

from itertools import (chain, repeat)

times = chain(repeat(True, 2), repeat(False))
while next(times):
    print 'do stuff!'

В этом примере 2 - это количество раз для итерации цикла. цепочка обертывает два итератора repeat, первый из которых ограничен, а второй бесконечен. Помните, что это истинные объекты итератора, поэтому они не требуют бесконечной памяти. Очевидно, это намного медленнее, чем решение # 1. Если не указано как часть функции, может потребоваться очистка переменной times.

Ответ 10

Вместо ненужного счетчика теперь у вас есть ненужный список. Лучшее решение - использовать переменную, начинающуюся с "_", которая сообщает синтаксическим шашкам, что вы знаете, что вы не используете переменную.

x = range(5)
while len(x) > 0:
  x.pop()
  print "Work!"

Ответ 11

Мы получили удовольствие от следующего, интересного поделиться так:

class RepeatFunction:
    def __init__(self,n=1): self.n = n
    def __call__(self,Func):
        for i in xrange(self.n):
            Func()
        return Func


#----usage
k = 0

@RepeatFunction(7)                       #decorator for repeating function
def Job():
    global k
    print k
    k += 1

print '---------'
Job()

Результаты:

0
1
2
3
4
5
6
---------
7

Ответ 12

Если do_something является простой функцией или может быть завернута в одну, простой map() может do_something range(some_number) раз:

map(do_something, range(some_number))

Если вы хотите передать аргументы в do_something, вы также можете найти itertools repeatfunc recipe:

Чтобы передать те же аргументы:

import itertools
args = [..., my args here, ...]
itertools.starmap(do_something, itertools.repeat(args, some_number)) 

Чтобы передать разные аргументы:

import itertools
argses = [[1, 2], [3, 4], ...]
itertools.starmap(do_something, argses) 

Ответ 14

Если вы действительно хотите избежать помещать что-то с именем (либо переменной итерации, как в OP, либо нежелательным списком, либо нежелательным генератором, возвращающим истинное требуемое количество времени), вы можете сделать это, если вы действительно хотели:

for type('', (), {}).x in range(somenumber):
    dosomething()

Используется трюк для создания анонимного класса type('', (), {}), который приводит к классу с пустым именем, но NB, что он не вставлен в локальное или глобальное пространство имен (даже если было дано непустое имя). Затем вы используете член этого класса как переменную итерации, которая недоступна, поскольку класс, членом которого он недоступен, не доступен.

Ответ 15

В соответствии с тем, что сказал Алекс Мартелли. Неверно, что itertools.repeat() быстрее, чем range.

Я запускал несколько раз генерации случайных чисел в цикле for, используя оба метода итерации. В основном в повторах до 100 000 раз range быстрее, чем itertools.repeat(). Но когда дело доходит до повторения более 100 000 раз, оно itertools.repeat(), которое быстрее, чем range.

10000 times
Itertools: 0.015010
Range: 0.008006`

100000 times
Itertools: 0.091061
Range: 0.087057

1000000
Itertools: 0.846565
Range: 0.911609

Я генерировал кортежи случайных целых чисел в списке. С уважением Марек

Ответ 16

Как насчет:

while range(some_number):
    #do something