Наиболее питонический способ, эквивалентный для:while ((x = следующий()) != КОНЕЦ)
Вопрос
Какая идиома Python лучше всего подходит для этой конструкции C?
while ((x = next()) != END) {
....
}
У меня нет возможности перекодировать next().
Обновить:и ответ, по-видимому, таков:
for x in iter(next, END):
....
Решение
Краткий ответ:в Python нет способа выполнить встроенное присвоение переменной в цикле while.Это означает , что я не могу сказать:
while x=next():
// do something here!
Поскольку это невозможно, существует ряд "идиоматически правильных" способов сделать это:
while 1:
x = next()
if x != END:
// Blah
else:
break
Очевидно, что это как-то некрасиво.Вы также можете использовать один из "итераторных" подходов, перечисленных выше, но, опять же, это может быть не идеально.Наконец, вы можете использовать подход "pita pocket", который я только что нашел во время поиска в 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 x in iter(next_, END):
....
Вот выдержка из Документация Python:
iter(o[, sentinel])
Возвращает объект итератора. ... (снип)... Если второй аргумент,
sentinel
, задается, тогдаo
должен быть вызываемый объект.Созданный в этом случае итератор вызоветo
без каких-либо аргументов для каждого вызова своегоnext()
способ;если возвращаемое значение равноsentinel
,StopIteration
будет увеличено, в противном случае значение будет возвращено.
Это немного зависит от того, что вы хотите сделать.Чтобы максимально соответствовать вашему примеру, я бы создал next генератор и повторил его:
def next():
for num in range(10):
yield num
for x in next():
print x
Может быть, это не очень идиоматично, но я бы склонен согласиться с
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 ]
, чтобы получить все четные числа в списке).
Можете ли вы предоставить больше информации о том, чего вы пытаетесь достичь?Мне непонятно, почему ты не можешь просто сказать
for x in everything():
...
и пусть функция everything возвращает все, вместо того чтобы писать следующую функцию, которая просто возвращала бы что-то одно за раз.Генераторы могут даже делать это довольно эффективно.
Если вам нужно сделать это более одного раза, питонический способ будет использовать итератор
for x in iternext():
do_something_with_x
где iternext
было бы определено с помощью чего-то вроде
(явное лучше неявного!):
def iternext():
x = next()
while x != END:
yield x
x = next()