2009-12-24 11 views

risposta

17

a. Spell bene: non

def __iter(self): 

ma:

def __iter__(self): 

con __ prima e dopo iter.

b. Rendere il corpo a destra: non

return 33 

ma:

yield 33 

o ritorno iter ([33])

Se return un valore da __iter__, restituire un iteratore (un iterable, come in return [33], è quasi altrettanto buono ma non del tutto ...); oppure, yield valori 1+, rendendo __iter__ in una funzione di generatore (quindi restituisce intrinsecamente un iteratore di generatore).

c. Chiamatela destra: non

a().itervalues() 

ma, ad es .:

for x in a(): print x 

o

print list(a()) 

itervalues è un metodo di dict, e non ha nulla a che fare con __iter__.

Se si risolvono tutti e tre gli errori (!), Il codice funziona meglio ;-).

+0

Ma se sta solo tornando (cedendo) 33, è davvero un * iteratore *? –

+0

Bene, se ** si produce ** 33, allora sì, allora il metodo diventa un'espressione generatore, che produce un iteratore. Quando ritorni [33], beh, un elenco è certamente iterabile, quindi funziona anche. – shylent

+1

@Goose e @Shylent, yep: 'yield 33' rende' __iter__' una funzione di generatore (** not ** generator _expression_ - che è un costrutto diverso ;-), quindi restituisce un generatore, che è un iteratore; 'return [33]' restituisce un iteratore iterabile ma non un iteratore, quindi è leggermente imperfetto - modifica la risposta per correggere quel cavillo! -) –

5

alcune cose circa il vostro codice:

  1. __iter dovrebbero essere __iter__
  2. Stai tornando '33' nel Funzione __iter__.Si dovrebbe effettivamente restituire un oggetto iteratore . Un iteratore è un oggetto che continua a restituire valori diversi quando si chiama la funzione next() (forse una sequenza di valori come [0,1,2,3 ecc.]).

Ecco un esempio di lavoro di un iteratore:

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 

Ogni oggetto della classe a è un oggetto iteratore. Chiamando la funzione __iter__ si suppone che restituisca l'iteratore, quindi restituisce stesso - come si può vedere, la classe ha una funzione next(), quindi questo è un oggetto iteratore.

Quando la funzione successivo è chiamato, esso mantiene restituire valori consecutivi finché non raggiunge lo zero, e quindi invia l'eccezione StopIteration, che (opportunamente) arresta l'iterazione.

Se questo vi sembra un po 'confuso, vorrei suggerire a sperimentare con il codice e poi controllando la documentazione qui: http://docs.python.org/library/stdtypes.html

1

Ecco un esempio di codice che implementa la funzione interna 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

cosa significa questo codice. assert (int (skip)! = 0) – zjm1126

+0

Questo dice a Python di lanciare un'eccezione se skip è 0. Se skip è 0 l'iteratore non terminerà mai e stamperà sempre lo stesso valore. – Omnifarious

+0

Non è necessario ed è solo lì per rendere la classe più sicura da usare. Può essere rimosso senza danno. – Omnifarious

Problemi correlati