>  기사  >  백엔드 개발  >  Python 생성기 정의 및 간단한 사용 사례 분석

Python 생성기 정의 및 간단한 사용 사례 분석

不言
不言원래의
2018-05-02 16:04:571164검색

이 글에서는 주로 Python 생성기의 정의와 간단한 사용법을 소개합니다. Python 생성기의 개념, 원리, 사용 방법 및 관련 작동 주의사항을 예제 형식으로 자세히 분석합니다. 도움이 필요한 친구가 참고할 수 있습니다. 예제 Python 생성기 정의 및 간단한 사용법. 참고할 수 있도록 모든 사람과 공유하세요. 세부 사항은 다음과 같습니다.

1. 생성기란 무엇입니까 Python에서는 메모리 제한으로 인해 목록 용량이 확실히 제한되어 있습니다. 예를 들어, 1억 개의 요소가 포함된 목록을 생성하는 경우 Python은 먼저 1억 개의 요소가 포함된 목록을 저장할 수 있도록 메모리에 충분한 공간을 연 다음 사용자가 목록을 사용할 수 있도록 허용합니다. 이로 인해 다음과 같은 문제가 발생할 수 있습니다.

 1. 이 목록을 저장할 메모리 공간이 부족하여 목록을 생성할 수 없습니다

 2. 목록이 성공적으로 생성되더라도 시간이 오래 걸려서 프로그램이 부족합니다. 효율성

 3. 사용자가 목록의 처음 몇 가지 요소에만 액세스하려는 경우 다음 목록의 대부분의 요소가 차지하는 공간이 낭비됩니다

위 문제를 효과적으로 해결하기 위해 Python은 "

계산 중 루프

" 메커니즘이라는 새로운 방법을 도입했습니다.

는 사용자가 객체를 사용해야 할 때 Python이 메모리 공간을 열어 사용자가 미리 설계된 규칙에 따라 사용할 수 있도록 이 객체를 생성한다는 의미입니다. 목록처럼 미리 모든 객체를 생성한 다음 사용자에게 제공하는 대신 을 사용하세요. 이 메커니즘을 Python에서는 생성기라고 합니다.

2. 생성기 생성

A. 생성기 푸시 공식

은 생성기 파생이 [] 대신 ()를 사용하고 최종 반환이 다음과 같다는 점을 제외하면 목록 푸시 공식과 유사합니다. 목록이 아닌 생성기

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

작업 결과:

78946c0b3ac8a7ade0335cde177a2eb9 at 0x0000000002263150>

B에는 함수 정의에 Yield 키워드가 포함되어 있습니다. 함수는 더 이상 일반 함수가 아니라 생성기입니다.

[설명]: 항복 명령은 함수를 일시 중지하고 중간 결과를 반환할 수 있습니다. 이 명령을 사용하는 함수는 실행 환경을 저장하고 필요할 때 업데이트합니다.

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)

연산 결과:

5803358a1103d13381d03415effc78ac

[참고]: 일반 함수와 생성기가 되는 함수의 차이점:

order 실행되면 반환됩니다. 언제 return 또는 function 문의 마지막 줄을 만났습니다. 제너레이터가 되는 함수는 __next__() 메소드가 호출될 때마다 실행됩니다. Yield 문을 만나면 반환됩니다. 다시 실행되면 지난 번 반환된 Yield 문에서 계속됩니다.

f=fib(6)
print(f)
print(f.__next__())
print(f.__next__())
print(&#39;暂停一下&#39;)
print(f.__next__())
print(f.__next__())
작업 결과:

& lt; Generator Object Fib at 0x00000000025631a8 & gt; 1 1

Pause 생성기 방법 (참조 : Bole Online). 호출은 나중에 StopIteration 예외를 직접 반환합니다

def func():
  yield 1
  yield 2
  yield 3
g=func()
g.__next__()
g.close() #手动关闭生成器
g.__next__() #关闭后,yield 2和yield 3语句将不再起作用
작업 결과:



추적(가장 최근 호출 마지막):
파일 "E:py3DemoHellogeneratorDemo.py", line 9, in 4225fa317875f3e92281a7b1a5733569
g .__next__() # 닫은 후에는 Yield 2 및 Yield 3 문이 더 이상 작동하지 않습니다.
StopIteration

2.__next__() 메서드: 생성기의 다음 호출을 반환합니다.

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

[프로세스 설명]:

일반 제너레이터의 경우 __next__() 메서드에 대한 첫 번째 호출은 제너레이터를 시작하는 것과 동일합니다. 이때 실행은 생성기 함수의 첫 번째 라인부터 시작하여 에 대한 Yield 문(네 번째 라인)이 실행될 때까지 진행됩니다. 처음으로 생성이 종료됩니다.



두 번째 __next__() 메서드가 호출되면 생성기 함수가 다시 입력되고 Yield 문으로 다시 실행될 때까지 Yield 문의 다음 문(다섯 번째 줄)부터 실행이 시작됩니다. 실행, 세대는 장치 기능을 다시 뛰어오를 것입니다.

다음 __next__() 메소드 호출은 위와 동일합니다

3.send() 메소드: 외부에서 전달된 변수를 받아들이고, 변수 내용에 따라 결과를 계산하여 반환합니다. 생성기 함수

[참고]:

(1) send() 메서드는 __next__() 메서드와 유사하지만 send() 메서드는 항복 표현식 값에 전달될 수 있다는 점입니다. __next__() 메서드는 특정 값을 전달할 수 없으며, None만 항복 표현식에 전달할 수 있으므로 Generator.__next__()는 Generator.send(None)

으로 이해될 수 있습니다.

(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;))

运行结果:

0
Got:aaa
Got:3
Traceback (most recent call last):
  File "E:\py3Demo\Hello\generatorDemo.py", line 13, in 4225fa317875f3e92281a7b1a5733569
    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))

运行结果:

Traceback (most recent call last):
  File "E:\py3Demo\Hello\generatorDemo.py", line 17, in 4225fa317875f3e92281a7b1a5733569
    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;)

运行结果:

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装饰器原理与用法分析


위 내용은 Python 생성기 정의 및 간단한 사용 사례 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.