Python 生成器的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
woshichuanqilz
V2EX    Python

Python 生成器的问题

  •  
  •   woshichuanqilz 2021-07-02 10:40:52 +08:00 2838 次点击
    这是一个创建于 1612 天前的主题,其中的信息可能已经有所发展或是发生改变。

    学习 python 生成器的时候遇到一个问题, 生成器的目的是减少空间占用, 所以每次只是返回一个值. 再有通项公式的时候我能理解, 每一项实际上都可以算出来这样就不用记录全部的元素了. 但是如果我随便找一个没有规律的 list 做成生成器, 那么空间的节约体现在哪里呢? 比如我有这样的代码

    (x for x in [1,5,-1,10])

    假设我的这个 list 是没有规律的, 那么这个生成器是不是要存下来整个的 list, 那么空间的节约体现在哪里?

    14 条回复    2021-07-04 22:29:02 +08:00
    HashV2
        1
    HashV2  
       2021-07-02 10:44:29 +08:00
    你内存里都已经有 list 了,为什么还要用生成器去遍历,直接遍历你的 list 不就好了

    想省内存,就想办法把你最开始那个 list 写成生成器
    yufpga
        2
    yufpga  
       2021-07-02 10:53:14 +08:00
    首先生成器的目的并不是为了减少空间占用。其次你要搞明白生成器的原理, 就绕不开理解 yield 的机制。(x for x in [1,5,-1,10]) 等价于:

    def gen():
    for i in [1, 5, -1, 10]:
    yield i

    g = gen()
    wuwukai007
        3
    wuwukai007  
       2021-07-02 10:54:48 +08:00
    @yufpga 你这个也占用内存得啊。
    est
        4
    est  
       2021-07-02 10:57:05 +08:00
    mylist = [1,5,-1,10]
    (x*2 for x in mylist)
    (x/2 for x in mylist)


    这这种就节约空间了。不用存 3 份。
    HashV2
        5
    HashV2  
       2021-07-02 10:59:12 +08:00
    @yufpga #2 这种惰性的迭代器不就是为了减少内存占用的么? 不为这个的话是为了什么啊
    yufpga
        6
    yufpga  
       2021-07-02 11:08:52 +08:00
    @wuwukai007
    @HashV2
    我并没有在解释节省内存的问题,我在说的是生成器的原理,解释元祖形式的列表生成器的本质。

    可以去看看 python 生成器的 PEP ( https://www.python.org/dev/peps/pep-0255/), 该有的里面都有.

    事实上,你们也看到,生成器不一定总是会减少内存占用
    yufpga
        7
    yufpga  
       2021-07-02 11:12:23 +08:00
    @HashV2 你说的惰性迭代器缺失可以减少内存占用,但生成器的应用场景不只是迭代器上
    HashV2
        8
    HashV2  
       2021-07-02 11:17:38 +08:00
    @yufpga #7
    abersheeran
        9
    abersheeran  
       2021-07-02 12:22:20 +08:00
    你的场景不对。

    比如你要处理一个 31Gb 的文件,你电脑却只有 16G 内存,该怎么办呢?这时候用 yield file.read(4096) 进行流式处理。就能大幅度节约内存空间。
    BeautifulSoap
        10
    BeautifulSoap  
       2021-07-02 12:36:39 +08:00   2
    谈生成器不谈迭代器的话你当然搞不清楚这么搞是为什么

    生成器的一个目的是方便遍历啊,一些情况下的确可以省内存,但是重点是方便遍历啊,方便遍历啊(重要的说三遍

    迭代器通过统一了__next__()和__iter__()两个接口,可以让使用者不用在乎你内部结构多么复杂,你只要用 iter()和 next()这两个方法都可以轻松遍历。并且学过迭代器的人难道忘了么,你一直习以为常在用的 `for i in xxxx` 这写法实际上就是个语法糖 iter()和 next()写法的语法糖啊。省内存只不过是迭代器带来的优点之一,根本目的还是统一了接口可以让你轻松遍历对象


    然后就是生成器,生成器可以部分看作是迭代器的语法糖(虽然 yield 作用不止是语法糖),你手写迭代器需要实现__next__()和__iter__()两个接口,而用 yield 构建的生成器只需要简单几行代码就行了,生成器和迭代器一样可以使用 next()迭代,也能用 `for in xxx` 这个语法糖,所以,本质上还是为了方便遍历啊
    Lemeng
        11
    Lemeng  
       2021-07-02 12:46:19 +08:00
    路过,学习一下
    deplives
        12
    deplives  
       2021-07-02 13:45:19 +08:00
    因为当你如果有一个几百 G 文件需要遍历而你的内存只有 512M,你就知道他是干啥的
    ipwx
        13
    ipwx  
       2021-07-04 22:24:48 +08:00
    那如果你 [1, 5, -1, 10] 是从文件读出来的呢。。。? 你可以每次只读 100 个,但是返回一个丢出去。多好
    shendun
        14
    shendun  
       2021-07-04 22:29:02 +08:00
    @ipwx 大佬求联系方式 聊几句可以吗
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     950 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 23:11 PVG 07:11 LAX 15:11 JFK 18:11
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86