#for-loop #iterator #python
#for-цикл #итератор #python
Вопрос:
Проблема довольно проста, у меня есть метод, который возвращает список. Я хочу перебрать каждый элемент в этом списке, а после завершения вызвать метод для получения нового списка и повторить.
На данный момент мой код выглядит примерно так:
generator = iter([])
while Condition:
try:
item = next(generator)
except StopIteration:
generator = iter(list_returining_method())
item = next(generator)
...
Однако ранее я использовал вложенный for
цикл.
while Condition:
for item in list_returining_method():
...
Хотя моя предыдущая попытка выглядит лучше в некоторых отношениях, но мой текущий метод имеет некоторые «преимущества»:
- если для условия установлено значение false, цикл завершается без необходимости
break
выхода из цикла for.- в дополнение к вышеуказанным причинам методы с доступом к условию могут завершить цикл, не просматривая все другие элементы в указанном списке или не выполняя специальную проверку в цикле for.
- Первый подход позволяет пропускать элементы в цикле, если возникнет необходимость.
- Существует также на один уровень отступа меньше. Это больше тщеславия, чем что-либо еще, но, учитывая, что фактический код был частью метода класса, уровень отступа уже был довольно высоким.
По меньшей мере, я смущен тем, что является более подходящим. Похоже, что они оба имеют уникальные преимущества и недостатки, поэтому, если кто-нибудь знает наиболее правильный и питонический подход, я был бы очень признателен.
Ответ №1:
Я бы посоветовал вам использовать некоторые итераторы
items = itertools.chain.from_iterable( iter(list_returning_method, None) )
for item in items:
# do something with item
print item
if not Condition:
break
iter(callable, sentinel)
возвращает итератор, который выдает результат callable(), пока не вернет sentinel .
itertools.chain.from_iterable
возвращает итератор, который выравнивает исходный итератор, он будет создавать значения в списках, созданных первым итератором.
Я думаю, что это дает вам большинство преимуществ вашего метода, но с более чистым стилем.
Комментарии:
1. Это работает очень хорошо. Хотя первая строка изначально выглядела довольно загадочно, это гораздо лучшее решение. Единственная проблема, которую я вижу в этом, заключается в том, что передача аргументов вызываемому объекту необходима. Любые предложения о том, как решить эту проблему?
2. @SingularityCat, есть два варианта. Вы можете использовать functools.partial, который объединяет функцию и аргументы для создания новой функции. Или вы можете написать генератор.
Ответ №2:
Здесь есть место для мнений, но краткость второго подхода делает его явным выигрышем, насколько я понимаю. Особенно, если использование item
переменной ограничено внутри цикла, я бы каждый раз выбирал синтаксис for / in . Были некоторые проблемы, связанные с буферами и изменениями состояния в цикле, где я решил не использовать for / in . Но это небольшое меньшинство.