Наиболее Pythonic способ эквивалентен для: while ((x = next ())! = END) - PullRequest
10 голосов
/ 26 августа 2008

Какая идиома Python для этой конструкции C?

while ((x = next()) != END) {
    ....
}

У меня нет возможности перекодировать next ().

обновление: и ответ, кажется, будет:

for x in iter(next, END):
    ....

Ответы [ 7 ]

14 голосов
/ 09 января 2009

@ Марк Харрисон ответил:

for x in iter(next_, END):
    ....

Вот выдержка из документации Python :

iter(o[, sentinel])

Вернуть объект итератора. ... (snip) ... Если задан второй аргумент sentinel, тогда o вызываемый объект. Итератор созданный в этом случае вызовет o без аргументов для каждого вызова его next() метод; если значение вернулось равно sentinel, StopIteration будет поднят, в противном случае будет возвращено значение.

5 голосов
/ 26 августа 2008

Это немного зависит от того, что вы хотите сделать. Чтобы максимально соответствовать вашему примеру, я бы сделал следующий генератор и перебрал его:

def next():
   for num in range(10):
      yield num

for x in next():
   print x
4 голосов
/ 26 августа 2008

Краткий ответ: в Python нет способа встроенного назначения переменных в цикле while. Это означает, что я не могу сказать:

while x=next():
    // do something here!

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

while 1:
    x = next()
    if x != END:
        // Blah
    else:
        break

Очевидно, это немного уродливо. Вы также можете использовать один из «итераторных» подходов, перечисленных выше, но, опять же, это может быть не идеально. Наконец, вы можете использовать подход «pita pocket», который я только что нашел, когда гуглил:

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__ идиоме было действительно здорово! :)

РЕДАКТИРОВАТЬ: Я хотел бы дать кредит, когда кредит должен. Идиома «карманный лаваш» была найдена здесь

2 голосов
/ 26 августа 2008

Может быть, это не очень идиоматично, но я бы склонен пойти с

x = next()
while x != END:
    do_something_with_x
    x = next()

... но это потому, что я нахожу такие вещи легко читаемыми

1 голос
/ 26 августа 2008

Можете ли вы предоставить больше информации о том, что вы пытаетесь достичь? Мне непонятно, почему ты не можешь просто сказать

for x in everything():
    ...

и заставить функцию all возвращать все, вместо того, чтобы писать следующую функцию, которая будет возвращать только одну вещь за раз. Генераторы могут даже сделать это довольно эффективно.

1 голос
/ 26 августа 2008

Если вам нужно сделать это более одного раза, питонский способ будет использовать итератор

for x in iternext():
    do_something_with_x

где iternext будет определено с использованием чего-то вроде ( явное лучше, чем неявное! ):

def iternext():
    x = next()
    while x != END:
        yield x
        x = next()        
1 голос
/ 26 августа 2008

Что вы пытаетесь сделать здесь? Если вы перебираете список, вы можете использовать for e in L, где e - элемент, а L - список. Если вы фильтруете список, вы можете использовать списки (например, [ e for e in L if e % 2 == 0 ], чтобы получить все четные числа в списке).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...