Definition des Python-Generators und Analyse einfacher Anwendungsbeispiele

不言
Freigeben: 2018-05-02 16:04:57
Original
1215 Leute haben es durchsucht

Dieser Artikel stellt hauptsächlich die Definition und einfache Verwendung von Python-Generatoren vor. Er analysiert die Konzepte, Prinzipien, Verwendungsmethoden und zugehörigen Vorsichtsmaßnahmen für den Betrieb von Python-Generatoren im Detail in Form von Beispielen.

Die Beispiele in diesem Artikel beschreiben die Definition und einfache Verwendung von Python-Generatoren. Teilen Sie es als Referenz mit allen. Die Details lauten wie folgt:

1. Was ist ein Generator?

In Python aus Speichergründen Einschränkungen: Die Listenkapazität ist sicherlich begrenzt. Wenn wir beispielsweise eine Liste mit 100 Millionen Elementen erstellen, öffnet Python zunächst genügend Speicherplatz, um die Liste mit 100 Millionen Elementen zu speichern, und ermöglicht dann dem Benutzer die Verwendung der Liste. Dies kann zu folgenden Problemen führen:

1. Es ist nicht genügend Speicherplatz im Speicher vorhanden, um diese Liste zu speichern, was dazu führt, dass die Liste nicht erstellt werden kann

2. Selbst wenn die Liste erfolgreich erstellt wurde, dauert sie noch eine lange Zeit, was zu einer Programmeffizienz führt Niedrig

3. Wenn der Benutzer nur auf die ersten paar Elemente der Liste zugreifen möchte, wird der von den meisten Elementen in der nachfolgenden Liste belegte Platz verschwendet

Um die oben genannten Probleme effektiv zu lösen, wird Python eingeführt. Ein neuer Mechanismus zum gleichzeitigen Schleifen und Berechnen bedeutet, dass der Benutzer ihn verwenden muss Wenn Sie ein Objekt erstellen, öffnet Python Speicherplatz und erstellt es gemäß den vorgefertigten Regeln. Dieses Objekt steht den Benutzern zur Verfügung, anstatt alle Objekte im Voraus zu erstellen und sie dann den Benutzern zur Verwendung bereitzustellen wie eine Liste. Dieser Mechanismus wird in Python als Generator bezeichnet.

2. Erstellung des Generators

A. Generator-Push-Formel

und der Listen-Push ist ähnlich, außer dass das Generatorverständnis () anstelle von [] verwendet und der Generator schließlich anstelle der Liste zurückgegeben wird

g=((i+2)**2 for i in range(2,30)) #g是一个生成器
print(g) #g为空,里面包含任何元素
Nach dem Login kopieren

Das Operationsergebnis:

< ;Generatorobjekt bei 0x0000000002263150>

B. yield keyword

enthält das yield-Schlüsselwort in einer Funktionsdefinition, dann ist diese Funktion keine gewöhnliche Funktion mehr Funktion, sondern ein Generator

[Erklärung]: Die yield-Anweisung kann eine Funktion anhalten und ihre Zwischenergebnisse zurückgeben. Die Funktion, die diese Anweisung verwendet, speichert die Ausführungsumgebung und stellt sie bei Bedarf wieder her

def fib(max):
  n,a,b=0,0,1
  while n<max:
    #print(b)
    yield b
    a,b=b,a+b
    n+=1
  return &#39;done&#39;
f=fib(6)
print(f)
Nach dem Login kopieren
Laufende Ergebnisse:

[Hinweis]: Der Unterschied zwischen gewöhnlichen Funktionen und Funktionen, die zu Generatoren werden:

Gewöhnliche Funktionen werden nacheinander ausgeführt und kehren zurück, wenn sie auf return oder die letzte Zeile von Funktionsanweisungen stoßen. Die Funktion, die zum Generator wird, wird jedes Mal ausgeführt, wenn die Methode __next__() aufgerufen wird, und kehrt zurück, wenn eine Yield-Anweisung auftritt. Bei erneuter Ausführung wird die Ausführung mit der Yield-Anweisung fortgesetzt, die beim letzten

f=fib(6)
print(f)
print(f.__next__())
print(f.__next__())
print(&#39;暂停一下&#39;)
print(f.__next__())
print(f.__next__())
Nach dem Login kopieren
-Ausführen zurückgegeben wurde Ergebnisse:

1

1
Pause
2
3

3. Generator-Methode (Referenz: Bole Online)

1.close()-Methode: Schließen Sie die Generatorfunktion manuell. Nachfolgende Aufrufe geben direkt eine StopIteration-Ausnahme zurück

def func():
  yield 1
  yield 2
  yield 3
g=func()
g.__next__()
g.close() #手动关闭生成器
g.__next__() #关闭后,yield 2和yield 3语句将不再起作用
Nach dem Login kopieren
Ergebnis ausführen:

Traceback (letzter Aufruf zuletzt):
Datei „E:py3DemoHellogeneratorDemo.py“, Zeile 9, in

g. ) #Nach dem Schließen funktionieren die Anweisungen yield 2 und yield 3 nicht mehr
StopIteration

2.__next__()-Methode: Gibt den nächsten Aufruf des Generators zurück

def func():
  n=1
  for i in range(3):
    yield n
    n+=1
c=func()
a1=c.__next__()
a2=c.__next__()
a3=c.__next__()
Nach dem Login kopieren

[Prozesserklärung]:

Bei einem gewöhnlichen Generator entspricht der erste Aufruf der Methode __next__() dem Starten des Generators Ausführung von der ersten Zeile der Generatorfunktion bis zur ersten Ausführung der Yield-Anweisung (vierte Zeile), dann springt die Generatorfunktion heraus.

Wenn die zweite Methode __next__() aufgerufen wird, wird die Generatorfunktion erneut eingegeben und die Ausführung beginnt mit der nächsten Anweisung (fünfte Zeile) der Yield-Anweisung, bis sie erneut ausgeführt wird -run. Die yield-Anweisung springt nach der Ausführung wieder aus der Generatorfunktion heraus.

Der nachfolgende Methodenaufruf __next__() ist derselbe wie die Methode

3.send(): akzeptiert eine von außen übergebene Variable , Und das Berechnungsergebnis wird basierend auf dem Variableninhalt an die Generatorfunktion zurückgegeben

[Hinweis]:

(1) send() Die Methode und die Methode __next__ () sind ähnlich. Der Unterschied besteht darin, dass die Methode send () an den Ertragsausdruckswert übergeben kann, während die Methode __next__ () keinen bestimmten Wert übergeben kann und nur None an den Ertragsausdruck übergeben kann, also

Dies kann als generator.__next__() und als generator.send(None) verstanden werden

(2)第一次调用生成器函数时,必须使用__next__()语句或是send(None),不能使用send发送一个非None的值给生成器函数,否则会出错,因为没有yield语句来接收这个值

def gen():
  value=0
  while True:
    receive=yield value
    if receive==&#39;end&#39;:
      break
    value=&#39;Got:%s&#39; %receive
g=gen()
print(g.__next__()) #或是print(g.send(None)),从而启动生成器
print(g.send(&#39;aaa&#39;))
print(g.send(3))
print(g.send(&#39;end&#39;))
Nach dem Login kopieren

运行结果:

0
Got:aaa
Got:3
Traceback (most recent call last):
File "E:\py3Demo\Hello\generatorDemo.py", line 13, in
print(g.send('end'))
StopIteration

[流程解释]:

a.通过g.send(None)或g.__next__()启动生成器函数,并执行到第一个yield语句结束的位置并将函数挂起。此时执行完了yield语句,但是没有给receive赋值,因此yield value会输出value的初始值0

b.g.send('aaa')先将字符串‘aaa'传入到生成器函数中并赋值给receive,然后从yield语句的下一句重新开始执行函数(第五句),计算出value的值后返回到while头部开始新一轮的循环,执行到yield value语句时停止,此时yield value会输出‘Got:aaa',然后挂起

c.g.send(3)重复步骤b,最后输出结果为‘Got:3'

d.g.send('end')会使程序执行break然后跳出循环,从而函数执行完毕,得到StopIteration异常

4.throw()方法:向生成器发送一个异常。

def gen():
  while True:
    try:
      yield &#39;normal value&#39; #返回中间结果,此处的yield和return的功能相似
      yield &#39;normal value2&#39;
      print(&#39;I am here&#39;)
    except ValueError:
      print(&#39;We got ValueError&#39;)
    except Exception:
      print(&#39;Other errors&#39;)
      break
g=gen()
print(g.__next__())
print(g.throw(ValueError))
print(g.__next__())
print(g.throw(TypeError))
Nach dem Login kopieren

运行结果:

Traceback (most recent call last):
File "E:\py3Demo\Hello\generatorDemo.py", line 17, in
print(g.throw(TypeError))
StopIteration
normal value
We got ValueError
normal value
normal value2
Other errors

[解释]:

a.print(g.__next__())会输出normal value,并停在yield 'normal value2'之前

b.由于执行了g.throw(ValueError),所以回跳过后续的try语句,即yield ‘normal value2'不会执行,然后进入到except语句,打印出‘We got ValueError'。之后再次进入到while语句部分,消耗一个yield,输出normal value

c.print(g.__next__())会执行yield ‘normal value2'语句,并停留在执行完该语句后的位置

d.g.throw(TypeError)会跳出try语句,因此print('I am here')不会被执行,然后打印‘Other errors',并执行break语句跳出while循环,然后到达程序结尾,打印StopIteration异常的信息

四、生成器的运用

import time
def consumer(name):
  print(&#39;%s准备吃包子啦!&#39; %name)
  while True:
    baozi=yield #接收send传的值,并将值赋值给变量baozi
    print(&#39;包子[%s]来了,被[%s]吃了!&#39; %(baozi,name))
def producer(name):
  c1=consumer(&#39;A&#39;) #把函数变成一个生成器
  c2=consumer(&#39;B&#39;)
  c1.__next__()#调用这个方法会走到yield处暂时返回
  c2.__next__()
  print(&#39;开始准备做包子啦!&#39;)
  for i in range(10):
    time.sleep(1)
    print(&#39;做了一个包子,分成两半&#39;)
    c1.send(i)
    c2.send(i)
producer(&#39;Tomwenxing&#39;)
Nach dem Login kopieren

运行结果:

A准备吃包子啦!
B准备吃包子啦!
开始准备做包子啦!
做了一个包子,分成两半
包子[0]来了,被[A]吃了!
包子[0]来了,被[B]吃了!
做了一个包子,分成两半
包子[1]来了,被[A]吃了!
包子[1]来了,被[B]吃了!
做了一个包子,分成两半
包子[2]来了,被[A]吃了!
包子[2]来了,被[B]吃了!
做了一个包子,分成两半
包子[3]来了,被[A]吃了!
包子[3]来了,被[B]吃了!
做了一个包子,分成两半
包子[4]来了,被[A]吃了!
包子[4]来了,被[B]吃了!
做了一个包子,分成两半
包子[5]来了,被[A]吃了!
包子[5]来了,被[B]吃了!
做了一个包子,分成两半
包子[6]来了,被[A]吃了!
包子[6]来了,被[B]吃了!
做了一个包子,分成两半
包子[7]来了,被[A]吃了!
包子[7]来了,被[B]吃了!
做了一个包子,分成两半
包子[8]来了,被[A]吃了!
包子[8]来了,被[B]吃了!
做了一个包子,分成两半
包子[9]来了,被[A]吃了!
包子[9]来了,被[B]吃了!

相关推荐:

Python迭代器定义与简单用法分析

Python装饰器原理与用法分析


Das obige ist der detaillierte Inhalt vonDefinition des Python-Generators und Analyse einfacher Anwendungsbeispiele. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage