




Может быть, это не совсем идиоматично, но я бы предпочел
x = next()
while x != END:
do_something_with_x
x = next()
... но это потому, что я нахожу такие вещи легко читаемыми
Что ты здесь делаешь?
Если вы перебираете список, вы можете использовать for e in L, где e - это элемент, а L - список. Если вы фильтруете список, вы можете использовать его понимание (например, [ e for e in L if e % 2 == 0 ], чтобы получить все четные числа в списке).
Это немного зависит от того, что вы хотите делать. Чтобы максимально соответствовать вашему примеру, я бы сделал следующий генератор и перебирал его:
def next():
for num in range(10):
yield num
for x in next():
print x
Если вам нужно сделать это более одного раза, питонический способ будет использовать итератор
for x in iternext():
do_something_with_x
где iternext можно определить с помощью чего-то вроде
(явное лучше, чем неявное!):
def iternext():
x = next()
while x != END:
yield x
x = next()
Краткий ответ: в Python нет возможности выполнять присваивание встроенной переменной в цикле while. Имея в виду, что я не можешь говорю:
while x=next():
// do something here!
Поскольку это невозможно, существует несколько «идиоматически правильных» способов сделать это:
while 1:
x = next()
if x != END:
// Blah
else:
break
Очевидно, это некрасиво. Вы также можете использовать один из перечисленных выше подходов «итератор», но, опять же, он может быть не идеальным. Наконец, вы можете использовать подход "лаваша", который я только что нашел во время поиска в Google:
class Pita( object ):
__slots__ = ('pocket',)
marker = object()
def __init__(self, v=marker):
if v is not self.marker:
self.pocket = v
def __call__(self, v=marker):
if v is not self.marker:
self.pocket = v
return self.pocket
Теперь вы можете:
p = Pita()
while p( next() ) != END:
// do stuff with p.pocket!
Спасибо за этот вопрос; узнать об идиоме __call__ было действительно круто! :)
Обновлено: Я хотел бы отдать должное, где причитается. Обнаружена идиома «лаваш в кармане» здесь
Использование генератора было бы более питоническим решением, если здесь проблема заключается в простом переборе списка, тогда достаточно цикла for, поскольку он выполняет самопроверку.
Можете ли вы предоставить дополнительную информацию о том, чего вы пытаетесь достичь? Мне непонятно, почему ты не можешь просто сказать
for x in everything():
...
и пусть функция everything возвращает все, вместо того, чтобы писать следующую функцию, чтобы просто возвращать одну вещь за раз. Генераторы даже могут делать это довольно эффективно.
Ответ @Mark Harrison:
for x in iter(next_, END):
....
Вот отрывок из Документация Python:
iter(o[, sentinel])
Return an iterator object. ...(snip)... If the second argument,
sentinel, is given, thenomust be a callable object. The iterator created in this case will callowith no arguments for each call to itsnext()method; if the value returned is equal tosentinel,StopIterationwill be raised, otherwise the value will be returned.
Использование
__slots__здесь совершенно не нужно.