> 백엔드 개발 > 파이썬 튜토리얼 > Python의 생성기는 어떻게 작동하나요?

Python의 생성기는 어떻게 작동하나요?

WBOY
풀어 주다: 2023-04-24 19:46:05
앞으로
1069명이 탐색했습니다.

파이썬 생성기란 무엇인가요?

생성기는 내부적으로 __iter____next__ 메서드를 갖는 특수 반복자입니다. >StopIteration 예외는 루프를 종료하지만 반복자와 비교하여 생성기는 "중간 값"을 저장하는 기능도 있으며 다음에 실행될 때 이 "중간 값"을 사용합니다. 생성기의 키워드는 yield입니다. 아래에서 가장 간단한 생성기를 작성해 보겠습니다. __iter__方法和__next__方法,在终止生成器的时候,还是会抛StopIteration异常以此来退出循环,只不过相比于迭代器,生成器还有特性会保存“中间值”,下次运行的时候,还会借助这个“中间值”来操作。生成器的关键字是yield,我们下面来写一个最简单的生成器。

#!/usr/bin/env python

def printNums():
    i = 0
    while i<10:
        yield i
        i = i + 1


def main():
    for i in printNums():
        print(i)

if __name__ == &#39;__main__&#39;:
    main()
로그인 후 복사

粗看代码,可能会觉着这个是个啥啊,为啥不直接用range来生成,偏偏要用yield,哎,不急,我们接着往下看为什么需要生成器,或者说,生成器解决了什么问题。

为什么需要python生成器

在说明这个问题之前,我们先来写一个需求,输出 0——10000000 以内的数据,而后运行查看导出内存运行截图。

调用python程序内存信息辅助说明

这里可以借助pythonmemory_profiler模块来检测程序内存的占用情况。

安装memory_profiler库:

pip3 install memory_profiler
로그인 후 복사

使用方法很简单,在需要检测的函数或者是代码前添加@profile装饰器即可,例如:

@profile
def main():
    pass
로그인 후 복사

生成.dat文件

mprof run

导出图示,可以使用

mprof plot --output=filename

python案例代码

以下2个程序,都是输出0—9999999之间的数据,不同的是,第一个程序是使用range而后给appendlist中,第二个则是使用迭代器来生成该数据。

main.py程序

@profile
def main():
    data = list(range(10000000))
    for i in data:
        pass

if __name__ == &#39;__main__&#39;:
    main()
로그인 후 복사

main_2.py程序

def printNum():
    i = 0 
    while i < 10000000:
        yield i
        i = i + 1

@profile
def main():
    for i in printNum():
        pass

if __name__ == &#39;__main__&#39;:
    main()
로그인 후 복사

运行程序

代码也有了,就可以按照上述来运行一下程序,并且导出内存信息

Python의 생성기는 어떻게 작동하나요?

运行后内存信息查看

main.py 运行内存图

Python의 생성기는 어떻게 작동하나요?

main_2.py 运行内存图

Python의 생성기는 어떻게 작동하나요?

如上2张对比图,当我们将数据叠加进列表,再输出的时候,占用内存接近400M,而使用迭代器来计算下一个值内存仅使用16M。

通过上述案例,我们应该知道为什么要使用生成器了吧。

python生成器原理

由于生成器表达式yield语句涉及到了python解释权内部机制,所以很难查看其源码,很难获取其原理,不过我们可以利用yield的暂停机制,来探寻一下生成器。

可以编写如下代码:

def testGenerator():
    print("进入生成器")
    yield "pdudo"
    print("第一次输出")
    yield "juejin"
    print("第二次输出")

def main():
    xx = testGenerator()
    print(next(xx))
    print(next(xx))

if __name__ == &#39;__main__&#39;:
    main()
로그인 후 복사

运行后效果如下

Python의 생성기는 어떻게 작동하나요?

通过上述实例,再结合下面这段生成器的运行过程,会加深对生成器的感触。

python遇到yield语句时,会记录当前函数的运行状态,并且暂停执行,将结果抛出。会持续等待下一次调用__next__方法,该方法调用后,会恢复函数的运行,直至下一个yield语句或者函数结束,执行到最后没有yield函数可执行的时候,会抛StopIteration来标志生成器的结束。

生成器表达式

python中,生成器除了写在函数中,使用yield返回之外,还可以直接使用生成器表达式,额。。。可能很抽象,但是你看下面这段代码,你就明白了。

def printNums():
    for i in [1,2,3,4,5]:
        yield i

def main():
    for i in printNums():
        print(i)

    gener = (i for i in [1,2,3,4,5])
    for i in gener:
        print(i)

if __name__ == &#39;__main__&#39;:
    main()
로그인 후 복사

其中,代码(i for i in [1,2,3,4,5])就等同于printNums函数,其类型都是生成器,我们可以使用typerrreee

코드를 보면 이것이 무엇인지 궁금할 것입니다. 왜 range를 사용하여 생성하지 않고 yield를 사용하면 될까요? 걱정하지 마세요. 그러면 발전기가 왜 필요한지, 즉 발전기가 어떤 문제를 해결하는지 살펴보겠습니다.

파이썬 생성기가 필요한 이유

Python의 생성기는 어떻게 작동하나요?이 문제를 설명하기 전에 먼저 0-10000000 범위의 데이터를 출력하라는 요구 사항을 작성한 다음 실행하여 내보낸 메모리 작업의 스크린샷을 살펴보겠습니다.

파이썬 프로그램 메모리 정보 호출을 위한 보조 지침

🎜여기서 pythonmemory_profiler 모듈을 사용하여 프로그램의 메모리 사용량을 감지할 수 있습니다. 🎜🎜memory_profiler 라이브러리 설치: 🎜rrreee🎜 사용법은 매우 간단합니다. 감지해야 하는 함수나 코드 앞에 @profile 데코레이터를 추가하면 됩니다. 예를 들면 다음과 같습니다. 🎜rrreee🎜 .dat 파일 생성 🎜
🎜mprof run 🎜
🎜다이어그램을 내보내려면 🎜
🎜mprof 플롯 --output=을 사용할 수 있습니다. filename🎜

python 케이스 코드

🎜 다음 두 프로그램은 모두 0-9999999 사이의 데이터를 출력합니다. 차이점은 첫 번째 프로그램이 range를 사용한 다음 list에 >append를 추가하고 두 번째는 반복자를 사용하여 데이터를 생성합니다. 🎜🎜main.pyProgram🎜rrreee🎜main_2.pyProgram🎜rrreee

프로그램 실행

🎜이제 코드가 있으므로 실행할 수 있습니다. 위 프로그램과 같이 하고 메모리 정보를 내보냅니다🎜🎜제너레이터의 원리는 무엇인가요? Python🎜

실행 후 메모리 정보 보기

🎜main.py 메모리 그래프 실행🎜🎜Python의 생성기 원리는 무엇입니까🎜🎜main_2.py 메모리 그래프 실행🎜🎜파이썬에서 제너레이터의 원리는 무엇인가요🎜🎜위의 두 비교사진처럼 겹쳐보면 데이터를 목록에 추가하고 출력할 때 거의 400M의 메모리를 차지하지만 반복자를 사용하여 다음 값을 계산하는 데는 16M의 메모리만 사용됩니다. 🎜🎜위의 사례를 통해 우리가 발전기를 사용하는 이유를 알아야 합니다. 🎜🎜Python 생성기 원리🎜🎜생성기 표현식 yield 문은 python 해석 능력의 내부 메커니즘을 포함하기 때문에 소스 코드를 보고 원리를 파악하기가 어렵습니다. , yield의 일시 중지 메커니즘을 사용하여 생성기를 탐색할 수 있습니다. 🎜🎜다음 코드를 작성할 수 있습니다. 🎜rrreee🎜실행 후 효과는 다음과 같습니다🎜🎜Python에서 생성기의 원리는 무엇인가요?🎜🎜위의 예를 통해 다음 생성기 작동 과정과 결합하여 생성기에 대한 이해가 깊어질 것입니다. 🎜🎜pythonyield 문을 발견하면 현재 함수의 실행 상태를 기록하고 실행을 일시 중지한 다음 결과를 발생시킵니다. __next__ 메서드에 대한 다음 호출을 계속 기다립니다. 이 메서드가 호출된 후 함수는 다음 yield 문이나 함수가 끝날 때까지 실행을 재개합니다. . 실행이 끝나면 가 없습니다. 항복 함수가 실행 가능하면 생성기의 끝을 표시하기 위해 StopIteration이 발생합니다. 🎜🎜생성기 표현식🎜🎜python에서는 함수에 생성기를 작성하고 yield를 사용하여 반환하는 것 외에도 생성기 표현식을 직접 사용할 수도 있습니다. . . 추상적일 수도 있지만, 아래 코드를 보시면 이해가 되실 겁니다. 🎜rrreee🎜그 중 (i for i in [1,2,3,4,5]) 코드는 printNums 함수와 동일하며 해당 유형은 다음과 같습니다. type을 사용하여 출력하여 살펴볼 수 있습니다. 🎜🎜코드를 변경하면 출력 결과는 다음과 같습니다.🎜🎜🎜🎜

위 내용은 Python의 생성기는 어떻게 작동하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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