2009-12-24 7 views

Répondre

17

a. Orthographier droite: pas

def __iter(self): 

mais:

def __iter__(self): 

avec __ avant et après iter.

b. Faites le bon corps: pas

return 33 

mais:

yield 33 

ou retour iter ([33])

Si vous return une valeur de __iter__, le retour d'un iterator (un itérable, comme dans return [33], est presque aussi bon mais pas tout à fait ...); ou sinon, yield 1+ valeurs, ce qui rend __iter__ dans une fonction de générateur (de sorte qu'il renvoie intrinsèquement un itérateur de générateur).

c. Appelez-le droit: pas

a().itervalues() 

mais, par exemple .:

for x in a(): print x 

ou

print list(a()) 

itervalues est une méthode de dict, et n'a rien à voir avec __iter__.

Si vous corrigez les trois erreurs (!), Le code fonctionne mieux ;-).

+0

Mais si il revient juste 33, est-ce vraiment un itérateur? –

+0

Eh bien, si vous ** cédez ** 33, alors oui, alors la méthode devient une expression génératrice, ce qui donne un itérateur. Quand vous revenez [33], eh bien, une liste est certainement itérable, donc ça marche aussi. – shylent

+1

@Goose et @Shylent, oui: 'yield 33' fait de' __iter__' une fonction de générateur (** pas ** generator_expression_ - c'est une construction différente ;-), donc ça retourne un générateur, qui est un itérateur; 'return [33]' renvoie un itérateur mais pas un itérateur, donc c'est un peu imparfait - édition de réponse pour corriger ce problème! -) –

5

Quelques choses sur votre code:

  1. __iter doivent être __iter__
  2. vous retournez '33' dans la __iter__ fonction.Vous devriez effectivement retourner un objet d'itérateur . Un itérateur est un objet qui continue à renvoyer des valeurs différentes lorsqu'il est next() la fonction est appelée (peut-être une séquence de valeurs comme [0,1,2,3 etc]).

Voici un exemple de travail d'un iterator:

class a(object): 
    def __init__(self,x=10): 
     self.x = x 
    def __iter__(self): 
     return self 
    def next(self): 
     if self.x > 0: 
      self.x-=1 
      return self.x 
     else: 
      raise StopIteration 

c=a() 

for x in c: 
    print x 

Tout objet de classe a est un objet iterator. Appeler la fonction __iter__ est supposé renvoyer l'itérateur, donc il retourne lui-même - comme vous pouvez le voir, la classe a une fonction next(), donc c'est un objet itérateur. Lorsque la fonction suivante est appelée, elle conserve les valeurs consécutives de retour jusqu'à ce qu'elle atteigne zéro, puis elle envoie l'exception StopIteration qui arrête (de façon appropriée) l'itération.

Si cela semble un peu brumeux, je suggère d'expérimenter avec le code, puis vérifier la documentation ici: http://docs.python.org/library/stdtypes.html

1

Voici un exemple de code qui implémente la commande interne xrange:

class my_xrange(object): 
    def __init__(self, start, end, skip=1): 
     self.curval = int(start) 
     self.lastval = int(end) 
     self.skip = int(skip) 
     assert(int(skip) != 0) 

    def __iter__(self): 
     return self 

    def next(self): 
     if (self.skip > 0) and (self.curval >= self.lastval): 
      raise StopIteration() 
     elif (self.skip < 0) and (self.curval <= self.lastval): 
      raise StopIteration() 
     else: 
      oldval = self.curval 
      self.curval += self.skip 
      return oldval 

for i in my_xrange(0, 10): 
    print i 
+0

qu'est-ce que ce code signifie. assert (int (skip)! = 0) – zjm1126

+0

Cela dit à Python de lancer une exception si skip vaut 0. Si skip vaut 0, l'itérateur ne se terminera jamais et affichera toujours la même valeur. – Omnifarious

+0

Il n'est pas nécessaire et est seulement là pour rendre la classe plus sûre à utiliser. Il peut être retiré sans dommage. – Omnifarious

Questions connexes