2008-08-26 5 views

Répondre

4

réponse courte: il n'y a pas moyen de faire variabl en ligne e affectation dans une boucle while en Python. Ce qui signifie que je ne peux pas dire:

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

Depuis ce n'est pas possible, il y a un certain nombre de « idiomatiquement corriger » façons de le faire:

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

De toute évidence, cela est une sorte de laid. Vous pouvez également utiliser l'une des approches «itérateur» énumérées ci-dessus, mais, encore une fois, cela peut ne pas être idéal. Enfin, vous pouvez utiliser l'approche « poche pita » que je viens de trouver en fait tout googler:

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 

Maintenant vous pouvez faire:

p = Pita() 
while p(next()) != END: 
    // do stuff with p.pocket! 

Merci pour cette question; apprendre sur le __call__ idiome était vraiment cool! :)

EDIT: Je voudrais donner un crédit lorsque le crédit est dû. L'idiome «poche de pita» a été trouvé here

+0

L'utilisation de '__slots__' est totalement inutile. – PaulMcG

+1

L'utilisation d'un générateur serait une solution plus pythonique, si l'on se contente ici de parcourir une liste, alors une boucle for suffit car elle se vérifie elle-même – synthesizerpatel

2

Peut-être pas terriblement idiomatiques, mais je serais enclin à aller avec

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

... mais c'est parce que je trouver ce genre de chose facile à lire

1

Qu'est-ce que vous essayez de faire ici? Si vous faites une itération sur une liste, vous pouvez utiliser for e in L où e est l'élément et L est la liste. Si vous filtrez une liste, vous pouvez utiliser les listes de compréhension (c'est-à-dire [ e for e in L if e % 2 == 0 ] pour obtenir tous les nombres pairs dans une liste).

5

Cela dépend un peu de ce que vous voulez faire. Pour correspondre à votre exemple dans la mesure du possible, je voudrais faire ensuite un générateur et itérer dessus:

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

for x in next(): 
    print x 
1

Si vous devez faire plus d'une fois, la façon pythonique utiliserait un itérateur

for x in iternext(): 
    do_something_with_x 

iternext serait défini en utilisant quelque chose comme (explicit is better than implicit!):

def iternext(): 
    x = next() 
    while x != END: 
     yield x 
     x = next()   
1

Pouvez-vous fournir plus d'informations sur ce que vous essayez d'accomplir? Il est pas clair pour moi pourquoi vous ne pouvez pas dire

for x in everything(): 
    ... 

et ont tout retour de la fonction tout, au lieu d'écrire une fonction suivante pour revenir juste une chose à la fois.Les générateurs peuvent même le faire assez efficacement.

14

Réponse de Harrison @ Mark:

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

Voici un extrait de Python's documentation:

iter(o[, sentinel]) 

Retour un objet iterator. ... (snip) ... Si le deuxième argument, sentinel, est donné, alors o doit être un objet appelable. L'itérateur créé dans ce cas appellera o sans argument pour chaque appel à sa méthode next(); si la valeur renvoyée est égale à sentinel, StopIteration sera élevée, sinon la valeur sera retournée.

Questions connexes