Python 생성기 소개 및 사용

零下一度
풀어 주다: 2017-07-19 23:25:52
원래의
1776명이 탐색했습니다.

파이썬의 생성기는 알고리즘을 저장하고 값은 실제로 필요한 경우에만 계산됩니다. 게으른 평가입니다.

생성기를 만드는 방법에는 두 가지가 있습니다.

첫 번째 방법: 목록 생성의 []를 ()로 변경하여 생성기를 만듭니다.

>>> L = [x * x for x in range(10)] >>> ; L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]>>> g = (x * x for x in range(10)) # 변경 후 [ ]를 ()로 변환하는 대신 튜플을 생성하는 대신 제너레이터 at 0x1022ef630>

함수에서 사용합니다. 발전기.

함수에 수율이 있는 후 수율에 도달하면 실행이 중지되고 추가 계산이 필요한 경우에만 계산이 계속됩니다. 따라서 생성기 함수에 무한 루프가 있어도 상관 없으며 계산해야 할 만큼 계산하고 필요하지 않으면 더 이상 계산하지 않습니다.

def fib():
a, b = 0, 1
while True:
Yield a
a, b = b, a + b
f = fib()
print f, next(f), next (f), next(f)
# 0 1 1

위의 예와 같이 f가 처음 출력되면 생성기이고 next가 나올 때마다 실행되면 .

물론, next()는 거의 사용되지 않습니다. for 루프를 직접 사용하여 생성기를 순회할 수 있습니다. 실제로 for 루프의 내부 구현은 next()를 계속 호출하는 것입니다.

생성기는 불필요한 계산을 피하고 성능을 향상시킬 수 있으며 공간을 절약하고 무한 루프(무한) 데이터 구조를 실현할 수 있습니다.

생성기 구문
생성기 표현식: 목록 구문 분석 구문을 사용하고, 목록 구문 분석에서 []를 ()로 바꾸면 됩니다.
제너레이터 표현식이 할 수 있는 것은 기본적으로 목록 구문 분석이 처리할 수 있지만 필요할 경우 처리되는 시퀀스가 ​​상대적으로 큰 경우, 목록 구문 분석은 더 많은 메모리를 소비합니다.

Generator 함수: 함수에 Yield 키워드가 나타나면 해당 함수는 더 이상 일반 함수가 아니라 생성기 함수입니다.

Python에서 Yield는 그러한 생성기입니다.

수익률 생성기의 작동 메커니즘:

생성기에 숫자를 요청하면 생성기는 수익률 문이 나타날 때까지 실행되며, 생성기는 수익률 매개변수를 제공하지만 생성기는 반환되지 않습니다. 계속 달려라. 당신이 그에게 다음 번호를 물으면 그는 마지막 상태부터 시작합니다. Yield 문이 나타날 때까지 실행을 시작하고 매개변수를 제공한 다음 중지합니다. 이는 함수가 종료될 때까지 반복됩니다.

yield 사용법:

Python에서 함수를 정의하고 Yield 키워드를 사용하면 함수의 실행은 return 문 대신 Object를 반환하는 일반 함수와 많이 다릅니다. 일반적으로 사용하는 결과 값을 얻을 수 있습니다. 값을 얻으려면 next() 함수를 호출해야 합니다. 다음은 Fibonacci의 예입니다. 이 줄이 실행되면 실행이 계속되지 않습니다. 대신, 현재 함수의 모든 매개변수의

상태를 포함하는 반복자 객체를 반환합니다. 값을 다시 할당하는 대신 두 번째 호출 시 함수의 모든 매개변수 값에 액세스할 수 있도록 하는 것이 목적입니다.

프로그램이 처음 호출될 때:

#coding:utf8
def fib(max): #10
    n, a, b = 0, 0, 1
    while n < max: #n<10
        #print(b)
        yield b
        a, b = b, a + b

        n += 1
    return 

f = fib(10)
for i in f:
    print f
로그인 후 복사

程序第二次调用时:

从前面可知,第一次调用时,a,b=0,0,那么,我们第二次调用时(其实就是调用第一次返回的iterator对象的next()方法),程序跳到yield语句处,

执行a,b = b, a+b语句,此时值变为:a,b = 0, (0+1) => a,b = 0, 1

程序继续while循环,当然,再一次碰到了yield a 语句,也是像第一次那样,保存函数所有参数的状态,返回一个包含这些参数状态的iterator对象。

等待第三次的调用....

通过上面的分析,可以一次类推的展示了yield的详细运行过程了!

通过使用生成器的语法,可以免去写迭代器类的繁琐代码,如,上面的例子使用迭代类来实现,代码如下:

#coding:UTF8

class Fib:  
    def __init__(self, max):  
        self.max = max
        print self.max
    def __iter__(self):  
        self.a = 0  
        self.b = 1 
        self.n = 0 
        return self  
    def next(self):  
        fib = self.n  
        if fib >= self.max:  
            raise StopIteration  
        self.a, self.b = self.b, self.a + self.b  
        self.n += 1
        return self.a
    
f = Fib(10)
for i in f:
    print i
로그인 후 복사

yield 与 return

在一个生成器中,如果没有return,则默认执行到函数完毕时返回StopIteration;

如果遇到return,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。

如果在return后返回一个值,会直接报错,生成器没有办法使用return来返回值。

生成器支持的方法(借鉴别人的例子,感觉蛮好的)

     close(...)
 |      close() -> raise GeneratorExit inside generator.
 |  
 |  next(...)
 |      x.next() -> the next value, or raise StopIteration
 |  
 |  send(...)
 |      send(arg) -> send &#39;arg&#39; into generator,
 |      return next yielded value or raise StopIteration.
 |  
 |  throw(...)
 |      throw(typ[,val[,tb]]) -> raise exception in generator,
 |      return next yielded value or raise StopIteration.
로그인 후 복사

close()

手动关闭生成器函数,后面的调用会直接返回StopIteration异常。

#coding:UTF8

def fib():
    yield 1
    yield 2
    yield 3

f = fib()
print f.next()
f.close()
print f.next()
로그인 후 복사

send()

生成器函数最大的特点是可以接受外部传入的一个变量,并根据变量内容计算结果后返回。
这是生成器函数最难理解的地方,也是最重要的地方,

def gen():
    value=0
    while True:
        receive=yield value
        if receive==&#39;e&#39;:
            break
        value = &#39;got: %s&#39; % receive
 
g=gen()
print(g.send(None))     
print(g.send(&#39;aaa&#39;))
print(g.send(3))
print(g.send(&#39;e&#39;))
로그인 후 복사

执行流程:

  1. 通过g.send(None)或者next(g)可以启动生成器函数,并执行到第一个yield语句结束的位置。此时,执行完了yield语句,但是没有给receive赋值。yield value会输出初始值0注意:在启动生成器函数时只能send(None),如果试图输入其它的值都会得到错误提示信息。

  2. 通过g.send(‘aaa’),会传入aaa,并赋值给receive,然后计算出value的值,并回到while头部,执行yield value语句有停止。此时yield value会输出”got: aaa”,然后挂起。

  3. 通过g.send(3),会重复第2步,最后输出结果为”got: 3″

  4. 当我们g.send(‘e’)时,程序会执行break然后推出循环,最后整个函数执行完毕,所以会得到StopIteration异常。

最后的执行结果如下:

0
got: aaa
got: 3
Traceback (most recent call last):
  File "1.py", line 15, in <module>
    print(g.send(&#39;e&#39;))
StopIteration
로그인 후 복사

 

throw()

用来向生成器函数送入一个异常,可以结束系统定义的异常,或者自定义的异常。
throw()后直接跑出异常并结束程序,或者消耗掉一个yield,或者在没有下一个yield的时候直接进行到程序的结尾。

def gen():
    while True: 
        try:
            yield &#39;normal value&#39;
            yield &#39;normal value 2&#39;
            print(&#39;here&#39;)
        except ValueError:
            print(&#39;we got ValueError here&#39;)
        except TypeError:
            break
 
g=gen()
print(next(g))
print(g.throw(ValueError))
print(next(g))
print(g.throw(TypeError))
로그인 후 복사

执行流程:

  1. print(next(g)):会输出normal value,并停留在yield ‘normal value 2’之前。

  2. 由于执行了g.throw(ValueError),所以会跳过所有后续的try语句,也就是说yield ‘normal value 2’不会被执行,然后进入到except语句,打印出we got ValueError here。然后再次进入到while语句部分,消耗一个yield,所以会输出normal value。

  3. print(next(g)),会执行yield ‘normal value 2’语句,并停留在执行完该语句后的位置。

  4. g.throw(TypeError):会跳出try语句,从而print(‘here’)不会被执行,然后执行break语句,跳出while循环,然后到达程序结尾,所以跑出StopIteration异常。

  

 

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

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!