Как я могу ограничить итерации цикла в Python?

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

items = list(range(10)) # I mean this to represent any kind of iterable.
limit = 5

наивная реализация

Python naïf, происходящий из других языков, вероятно, напишет этот совершенно исправный и эффективный (если unidiomatic) код:

index = 0
for item in items: # Python's `for` loop is a for-each.
    print(item)    # or whatever function of that item.
    index += 1
    if index == limit:
        break

более идиоматические реализации

но Python имеет enumerate, который прекрасно объединяет около половины этого кода:

for index, item in enumerate(items):
    print(item)
    if index == limit: # There's gotta be a better way.
        break

таким образом, мы о вырезать дополнительный код в половина. Но должен быть способ получше.

можем ли мы аппроксимировать приведенное ниже поведение псевдокода?

если enumerate взял еще один необязательный

5 ответов


как я могу ограничить итерации цикла в Python?

for index, item in enumerate(items):
    print(item)
    if index == limit:
        break

есть ли более короткий, идиоматический способ написать выше? Как?

включая индекс

zip останавливается на самой короткой итерации его аргументов. (В отличие от поведения zip_longest, который использует самую длинную итерацию.)

range может предоставить ограниченный iterable, который мы можем передать zip вместе с нашим основным повторяемый.

таким образом, мы можем пройти


можно использовать itertools.islice для этого. Он принимает start, stop и step аргументы, если вы передаете только один аргумент, то он считается как stop. И он будет работать с любым итерируемым.

itertools.islice(iterable, stop)
itertools.islice(iterable, start, stop[, step])

демо:

>>> from itertools import islice
>>> items = list(range(10))
>>> limit = 5
>>> for item in islice(items, limit):
    print item,
...
0 1 2 3 4

пример из docs:

islice('ABCDEFG', 2) --> A B
islice('ABCDEFG', 2, 4) --> C D
islice('ABCDEFG', 2, None) --> C D E F G
islice('ABCDEFG', 0, None, 2) --> A C E G

почему бы просто не использовать

for item in items[:limit]: # or limit+1, depends
    print(item)    # or whatever function of that item.

Это будет работать только для некоторых итераций, но поскольку вы указали списки, это работает.

Он не работает, если вы используете наборы или дикты и т. д.


Pass islice с пределом внутри перечислить

a = [2,3,4,2,1,4]

for a, v in enumerate(islice(a, 3)): 
   print(a, v)

выход:

0 2
1 3
2 4

почему бы не цикл до предела или конца списка, в зависимости от того, что происходит раньше, например:

items = range(10)
limit = 5
for i in range(min(limit, len(items))):
  print items[i]

выход:

0
1
2
3
4