Heim  >  Artikel  >  Backend-Entwicklung  >  Einführung in die Verwendung des Schlüsselworts yield in Python (Codebeispiel)

Einführung in die Verwendung des Schlüsselworts yield in Python (Codebeispiel)

不言
不言nach vorne
2018-12-15 10:09:442486Durchsuche

Dieser Artikel bietet Ihnen eine Einführung in die Verwendung des Schlüsselworts yield in Python (Codebeispiele). Ich hoffe, dass er für Freunde hilfreich ist.

Yield ist ein Schlüsselwort in Python, als ich zum ersten Mal mit diesem Schlüsselwort in Berührung kam. Erst nachdem ich es beherrschte, wurde mir klar, dass dieses Schlüsselwort sehr nützlich ist werde klären, wie yield zu verwenden ist.

1 Verwenden Sie yield, um einen Generator zu erstellen

In Python ist ein Generator ein iterierbares Objekt, aber ein iterierbares Objekt ist nicht unbedingt ein Generator.
Liste ist beispielsweise ein iterierbares Objekt

>>> a = list(range(3))
>>> for i in a:
    print(i)
0
1
2
3

Aber alle Werte eines Listenobjekts werden im Speicher gespeichert. Wenn die Datenmenge sehr groß ist, reicht der Speicher möglicherweise nicht aus In diesem Fall kann Python beispielsweise „()“ verwenden, um ein Generatorobjekt zu erstellen:

>>> b = (x for x in range(3))
>>> for i in b:
    print(i)

0
1
2
>>> for i in b:
    print(i)
    
>>>

Der Generator kann iteriert werden, und die Daten werden in Echtzeit generiert und nicht alle im Speicher gespeichert ist erwähnenswert Ja, der -Generator kann nur einmal gelesen werden. Wie Sie aus den obigen Laufergebnissen ersehen können, ist das Ausgabeergebnis der zweiten for-Schleife leer .

Wenn eine Funktion in der tatsächlichen Programmierung ein Stück serialisierter Daten generieren muss, besteht der einfachste Weg darin, alle Ergebnisse in eine Liste einzufügen und sie zurückzugeben. Wenn die Datenmenge groß ist, sollten Sie die Verwendung in Betracht ziehen ein Generator Um eine Funktion neu zu schreiben, die direkt eine Liste zurückgibt (Effective Python, Punkt 16).

>>> def get_generator():
    for i in range(3):
        print('gen ', i)
        yield i
        
>>> c = get_generator()    
>>> c = get_generator()
>>> for i in c:
    print(i)
    
gen  0
0
gen  1
1
gen  2
2

Wie aus dem obigen Code ersichtlich ist, wird beim Aufruf der get_generator-Funktion der Code in der Funktion nicht angezeigt ausgeführt wird, sondern ein Iterator-Objekt ist, wird der Code in der Funktion nur ausgeführt, wenn mit einer for-Schleife iteriert wird.
Zusätzlich zur Verwendung einer for-Schleife, um den vom Generator zurückgegebenen Wert zu erhalten, können Sie auch next und send verwenden

>>> c = get_generator()
>>> print(next(c))
gen  0
0
>>> print(next(c))
gen  1
1
>>> print(next(c))
gen  2
2
>>> print(next(c))
Traceback (most recent call last):
  File "<pyshell#59>", line 1, in <module>
    print(next(c))
StopIteration
rrree

Nachdem das Ergebnis des Generators gelesen wurde, wird eine StopIteration-Ausnahme ausgelöst generiert

2 Verwendung von

Yield in Coroutinen Ein häufiges Verwendungsszenario besteht darin, Coroutinen über Yield zu implementieren. Nehmen Sie das folgende Producer-Consumer-Modell als Beispiel:

>>> c = get_generator()
>>> c.send(None)
gen  0
0
>>> c.send(None)
gen  1
1
>>> c.send(None)
gen  2
2
>>> c.send(None)
Traceback (most recent call last):
  File "<pyshell#66>", line 1, in <module>
    c.send(None)
StopIteration
rrree

Wie Sie im obigen Beispiel sehen können, wird der Yield-Ausdruck mit „senden zum Datenaustausch“

# import logging
# import contextlib
# def foobar():
#     logging.debug('Some debug data')
#     logging.error('Some error data')
#     logging.debug('More debug data')
# @contextlib.contextmanager
# def debug_logging(level):
#     logger = logging.getLogger()
#     old_level = logger.getEffectiveLevel()
#     logger.setLevel(level)
#     try:
#         yield
#     finally:
#         logger.setLevel(old_level)
# with debug_logging(logging.DEBUG):
#     print('inside context')
#     foobar()
# print('outside context')
# foobar()
def consumer():
    r = 'yield'
    while True:
        print('[CONSUMER] r is %s...' % r)
        #当下边语句执行时,先执行yield r,然后consumer暂停,此时赋值运算还未进行
        #等到producer调用send()时,send()的参数作为yield r表达式的值赋给等号左边
        n = yield r #yield表达式可以接收send()发出的参数
        if not n:
            return # 这里会raise一个StopIteration
        print('[CONSUMER] Consuming %s...' % n)
        r = '200 OK'
def produce(c):
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)   #调用consumer生成器
        print('[PRODUCER] Consumer return: %s' % r)
    c.send(None)    
    c.close()
c = consumer()
produce(c)

3 im Kontextmanager

In verwendet Zusätzlich gibt es im Kontextmanager ein interessanteres Verwendungsszenario wie folgt:

[CONSUMER] r is yield...
[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[CONSUMER] r is 200 OK...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[CONSUMER] r is 200 OK...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[CONSUMER] r is 200 OK...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[CONSUMER] r is 200 OK...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[CONSUMER] r is 200 OK...
[PRODUCER] Consumer return: 200 OK
Traceback (most recent call last):
  File ".\foobar.py", line 51, in <module>
    produce(c)
  File ".\foobar.py", line 47, in produce
    c.send(None)
StopIteration
n = yield r
r = c.send(n)

Im obigen Code wird die Protokollebene vorübergehend durch die Verwendung des Kontextmanagers (contextmanager) erhöht, und yield stellt die Anweisung im with dar block;

Zusammenfassung

Der Yield-Ausdruck kann einen Generator erstellen, und Sie sollten erwägen, einen Generator zu verwenden, um die Funktion, die die Liste direkt zurückgibt, neu zu schreiben; 🎜>Da der Generator nur einmal gelesen werden kann, achten Sie besonders darauf, wenn Sie eine for-Schleife zum Durchlaufen verwenden. Wenn der Generator nach dem Lesen weiter liest, wird eine StopIteration-Ausnahme ausgelöst. In der tatsächlichen Programmierung kann diese Ausnahme verwendet werden eine Grundlage für die Beurteilung der Beendigung des Lesens;

Ein häufiges Verwendungsszenario für Yield ist die Implementierung von Coroutinen, die den Effekt des Datenaustauschs erzielen können stellt auch den with-Block in der durch contextmanager-Anweisung geänderten Funktion dar

Das obige ist der detaillierte Inhalt vonEinführung in die Verwendung des Schlüsselworts yield in Python (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen