Наиболее питонический способ, эквивалентный для:while ((x = следующий()) != КОНЕЦ)

StackOverflow https://stackoverflow.com/questions/28559

  •  09-06-2019
  •  | 
  •  

Вопрос

Какая идиома 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()        
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top