2009-12-24 2 views

Antwort

17

a. Formulieren Sie es richtig: nicht

def __iter(self): 

aber:

def __iter__(self): 

mit __ vor und nach iter.

b. Machen Sie den Körper rechts: nicht

return 33 

aber:

yield 33 

oder return iter ([33])

Wenn Sie return ein Wert von __iter__, einen Iterator zurückgeben (ein iterable, wie in return [33], ist fast so gut, aber nicht ganz ...); oder sonst, yield 1+ Werte, wodurch __iter__ zu einer Generatorfunktion gemacht wird (so dass es intrinsisch einen Generator-Iterator zurückgibt).

c. Nennen Sie es richtig: nicht

a().itervalues() 

aber, z.B .:

for x in a(): print x 

oder

print list(a()) 

itervalues ist ein Verfahren, dict, und hat nichts mit __iter__ zu tun.

Wenn Sie alle drei (!) Fehler beheben, funktioniert der Code besser ;-).

+0

Aber wenn Er kommt gerade zurück 33, ist das wirklich ein * Iterator *? –

+0

Nun, wenn Sie ** 33 ergeben, dann ja, dann wird die Methode ein Generatorausdruck, der einen Iterator ergibt. Wenn du zurückkommst [33], ist eine Liste sicherlich iterierbar, also funktioniert es auch. – shylent

+1

@Goose und @Shylent, yep: 'yield 33' macht '__iter__' zu einer Generatorfunktion (** not ** generator _expression_ - das ist ein anderes Konstrukt ;-), also gibt es einen Generator, der ein Iterator ist; 'return [33]' gibt einen iterierbaren, aber keinen Iterator zurück, also ist das ein wenig unvollkommen - Editier-Antwort, um dieses Problem zu beheben! -) –

5

Ein paar Dinge über Ihren Code:

  1. __iter__iter__
  2. sollten Sie Rückkehr '33' in der __iter__ Funktion.Sie sollten tatsächlich ein Iteratorobjekt zurückgeben. Ein Iterator ist ein Objekt, das immer unterschiedliche Werte zurückgibt, wenn die Funktion next() aufgerufen wird (möglicherweise eine Folge von Werten wie [0,1,2,3 usw.]).

Hier ist ein funktionierendes Beispiel eines Iterators:

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 

Jedes Objekt der Klasse a ist ein Iterator-Objekt. Der Aufruf der __iter__ Funktion soll den Iterator zurückgeben, also gibt es selbst zurück - wie Sie sehen können, hat die a-Klasse eine next()-Funktion, also ist dies ein Iterator-Objekt.

Wenn die nächste Funktion aufgerufen wird, behält sie fortlaufende Werte zurück, bis sie Null erreicht, und sendet dann die Ausnahme StopIteration, die die Iteration (entsprechend) stoppt.

Wenn dies ein wenig verschwommen erscheint, würde ich mit dem Code Experimentieren Sie und dann hier in der Dokumentation Check-out: http://docs.python.org/library/stdtypes.html

1

Hier ist ein Codebeispiel, das die xrange builtin implementiert:

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

Was bedeutet dieser Code? assert (int (skip)! = 0) – zjm1126

+0

Das weist Python an, eine Ausnahme auszulösen, wenn skip 0 ist. Wenn skip 0 ist, wird der Iterator niemals terminieren und immer den gleichen Wert ausgeben. – Omnifarious

+0

Es ist nicht notwendig und dient nur dazu, die Klasse sicherer zu machen. Es kann ohne Schaden entfernt werden. – Omnifarious