2017-09-02 2 views
1

Wenn wir den folgenden Generator und die Generatorfunktion betrachten:Warum sollte ein Generator in seine Generatorfunktion übergeben werden?

def integers(): 
    """Infinite sequence of integers.""" 
    i = 1 
    while True: 
     yield i 
     i = i + 1 

def take(n, seq): 
    """Returns first n values from the given sequence.""" 
    seq = iter(seq) 
    result = [] 
    try: 
     for i in range(n): 
      result.append(seq.next()) 
    except StopIteration: 
     pass 
    return result 

print take(5, integers()) # prints [1,2,3,4,5] 

Warum die iter funktions eingebaut hat auf den Generator im Generatorfunktion aufgerufen werden? Der Code wird weiterhin ausgeführt und druckt den richtigen Wert ohne es aus.

+0

Versuchen Sie, diese Zeile zu entfernen und eine Liste zu übergeben. 'take ([1, 2, 3], 2)' –

Antwort

2

take nicht weiß, ob es einen Iterator (wie ein Generator) oder einen Behälter (zB eine Liste/Tupel/set) empfängt. In letzterem Fall ist Containern keine .next-Methode zugeordnet, sodass der Code fehlschlägt. Dein Code spielt auf Nummer sicher, anstatt ein Risiko einzugehen, was ich für eine gute Programmierpraxis halte.


Ein Beispiel (in python3):

def foo(): 
    yield from [1, 2, 3] 

x = iter([1, 2, 3]) 
y = iter(foo()) 

print(next(x), next(y)) # this would be `x.next()` in python2 
(1, 1) 

Im letzteren Fall wird die iter ist redundant, aber der Code funktioniert in beiden Fällen. Allerdings betrachten:

x = [1, 2, 3] 
print(next(x)) 
TypeError         Traceback (most recent call last) 
<ipython-input-351-cf05c93171ef> in <module>() 
----> 1 print(next(x)) 

TypeError: 'list' object is not an iterator 

Es sollte klar sein, warum die iter Anruf benötigt wird.

+0

Iteratoren * sind * iterables. Dies wird von der [Iteratorspezifikation] (https://docs.python.org/3/library/stdtypes.html#iterator.__iter__) benötigt. – user2357112

+0

@ user2357112 Ich habe Mühe, den richtigen Wortlaut zu finden ... was ist hier angebracht? –

+1

@ cᴏʟᴅsᴘᴇᴇᴅ Sie könnten sie als Container bezeichnen. –

0

Wenn Sie eine list oder tuple an Ihre take Funktion übergeben, haben sie keine next Methode.

>>> [1, 2, 3].next() # AttributeError: 'list' object has no attribute 'next' 

Mit iter auf einem list Sie geben einen listiterator, die eine next Methode hat.

>>> my_gen = iter([1, 2, 3]) 
>>> print(my_gen) 
<listiterator object at 0x108390a10> 
>>> my_gen.next() 
1 
>>> next(my_gen) 
2 
+0

'Listiterator' ist ein Iterator, aber kein Generator – vaultah

+0

@vaultah: Beat mich zu meiner Bearbeitung. :-) –

Verwandte Themen