2016-09-15 6 views
1

Ich habe versucht, selbst nach dieser Antwort zu suchen, aber da war zu viel Lärm.Machen Generatoren einfach neue Objekte mit __iter__ und nächsten Funktionen?

Sind Generatoren in Python nur ein Convenience-Wrapper für den Benutzer, um ein Iterator-Objekt zu erstellen?

Wenn Sie den Generator definieren:

def test(): 
    x = 0 
    while True: 
    x += 1 
    yield x 

ist einfach Python ein neues Objekt zu machen, Hinzufügen der __iter__ Methode, dann den Rest des Codes in die next Funktion setzen?

class Test(object): 

    def __init__(self): 
    self.x = 0 

    def __iter__(self): 
    return self 

    def next(self): 
    self.x += 1 
    return self.x 

Antwort

2

Nein. Wie so:

>>> def test(): 
... x = 0 
... while True: 
...  x += 1 
...  yield x 
... 
>>> type(test) 
<type 'function'> 

Also was es zurückbringt, ist ein Funktionsgegenstand. Details von dort werden behaart; Der kurze Weg ist, dass das Code-Objekt, das zur Funktion (test.func_code) gehört, durch eines der Flags in test.func_code.co_flags als Generator markiert wird.

Sie den Bytecode für test zerlegen kann, um zu sehen, dass es auch anders wie jede andere Funktion ist, abgesehen davon, dass eine Generatorfunktion enthält immer einen YIELD_VALUE Opcode:

>>> import dis 
>>> dis.dis(test) 
    2   0 LOAD_CONST    1 (0) 
       3 STORE_FAST    0 (x) 

    3   6 SETUP_LOOP    25 (to 34) 
     >> 9 LOAD_GLOBAL    0 (True) 
      12 POP_JUMP_IF_FALSE  33 

    4   15 LOAD_FAST    0 (x) 
      18 LOAD_CONST    2 (1) 
      21 INPLACE_ADD 
      22 STORE_FAST    0 (x) 

    5   25 LOAD_FAST    0 (x) 
      28 YIELD_VALUE 
      29 POP_TOP 
      30 JUMP_ABSOLUTE   9 
     >> 33 POP_BLOCK 
     >> 34 LOAD_CONST    0 (None) 
      37 RETURN_VALUE 

es so, wie Sie im Kopf haben zu tun beginnen die Schrecken nur ;-), wenn Sie darüber nachdenken, wie ein Objekt erstellen imitieren nur dies:

def test(): 
    yield 2 
    yield 3 
    yield 4 

Jetzt ist Ihre next() Methode nur zusätzlichen versteckten Zustand tragen müßte remem ber die yield kommt als nächstes. Wrap das in einigen geschachtelten Schleifen mit einigen Bedingungen, und "entroll" es in einen einzigen Eintrag next() wird ein Albtraum.

+0

Das ist genau die Antwort, nach der ich gesucht habe. Ich wusste nicht genau, wie ich sagen sollte, was die Sprache unter der Haube tat. Ich bin froh, dass Sie das "dis" -Modul verwendet haben - ich wusste, wonach ich suchen wollte, konnte aber nicht die Phrasierung finden, um die Ergebnisse tatsächlich zu finden. – Esteban

+0

In diesem Fall denke ich, dass es für Sie profitabel sein wird, die PEP zu lesen, in der die Generatoren zuerst vorgeschlagen wurden - Sie greifen jetzt genug, um den Großteil davon zu verstehen :-) https://www.python.org/dev/ peps/pep-0255 / –

2

Nein - Generatoren auch andere Methoden zur Verfügung stellen (.send, .throw, etc.) und kann für weitere Zwecke genutzt werden als nur Iteratoren machen (z Koroutinen).

In der Tat, generators sind ein ganz anderes Biest und eine Kernsprachefunktion. Es wäre sehr schwer (möglicherweise unmöglich), einen in Vanillepython zu erstellen, wenn sie nicht in die Sprache hineingebacken wären.


dies gesagt wurde, eine Anwendung von Generatoren ist :-) eine einfache Syntax zum Erstellen eines Iterators bereitzustellen.

+0

Danke. Ich war mir nur nicht sicher, ob beide Objekte am Ende auf denselben Bytecode herunterkamen. – Esteban

1

Sind Generatoren in Python nur ein Convenience-Wrapper für den Benutzer, um ein Iterator-Objekt zu erstellen?

No. generator A ist eine Funktion, in der als iterators Klasse sind. Daher kann der Generator kein Objekt des Iterators sein. Aber in gewisser Weise können Sie sagen, dass Generator ein vereinfachter Ansatz ist, Iterator wie Fähigkeit zu erhalten. Es bedeutet:

Alle Generatoren sind Iteratoren, aber nicht alle Iteratoren sind Generatoren.

Ich werde stark vorschlagen, dass Sie unter dem Wiki Link verweisen:

  • Iterator - quert eine Sammlung eines nach dem anderen
  • Generator - erzeugt eine Sequenz, ein Element zu einem Zeitpunkt

Ein Iterator ist normalerweise etwas, das über eine next-Methode verfügt, um das nächste Element aus einem Stream abzurufen. Ein Generator ist ein Iterator, der an eine Funktion gebunden ist.

Ich empfehle Ihnen zu verweisen: Difference between Python's Generators and Iterators.