学习 python 生成器的时候遇到一个问题, 生成器的目的是减少空间占用, 所以每次只是返回一个值. 再有通项公式的时候我能理解, 每一项实际上都可以算出来这样就不用记录全部的元素了. 但是如果我随便找一个没有规律的 list 做成生成器, 那么空间的节约体现在哪里呢? 比如我有这样的代码
(x for x in [1,5,-1,10])
假设我的这个 list 是没有规律的, 那么这个生成器是不是要存下来整个的 list, 那么空间的节约体现在哪里?
1
HashV2 2021-07-02 10:44:29 +08:00
你内存里都已经有 list 了,为什么还要用生成器去遍历,直接遍历你的 list 不就好了
想省内存,就想办法把你最开始那个 list 写成生成器 |
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() |
3
wuwukai007 2021-07-02 10:54:48 +08:00
@yufpga 你这个也占用内存得啊。
|
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 份。 |
6
yufpga 2021-07-02 11:08:52 +08:00
@wuwukai007
@HashV2 我并没有在解释节省内存的问题,我在说的是生成器的原理,解释元祖形式的列表生成器的本质。 可以去看看 python 生成器的 PEP ( https://www.python.org/dev/peps/pep-0255/), 该有的里面都有. 事实上,你们也看到,生成器不一定总是会减少内存占用 |
9
abersheeran 2021-07-02 12:22:20 +08:00
你的场景不对。
比如你要处理一个 31Gb 的文件,你电脑却只有 16G 内存,该怎么办呢?这时候用 yield file.read(4096) 进行流式处理。就能大幅度节约内存空间。 |
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` 这个语法糖,所以,本质上还是为了方便遍历啊 |
11
Lemeng 2021-07-02 12:46:19 +08:00
路过,学习一下
|
12
deplives 2021-07-02 13:45:19 +08:00
因为当你如果有一个几百 G 文件需要遍历而你的内存只有 512M,你就知道他是干啥的
|
13
ipwx 2021-07-04 22:24:48 +08:00
那如果你 [1, 5, -1, 10] 是从文件读出来的呢。。。? 你可以每次只读 100 个,但是返回一个丢出去。多好
|