1

Python 生成器的问题

 2 years ago
source link: https://www.v2ex.com/t/787076
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

V2EX  ›  Python

Python 生成器的问题

  woshichuanqilz · 2 小时 23 分钟前 · 377 次点击

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

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

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

11 条回复    2021-07-02 12:46:19 +08:00

HashV2

HashV2   2 小时 20 分钟前

你内存里都已经有 list 了,为什么还要用生成器去遍历,直接遍历你的 list 不就好了

想省内存,就想办法把你最开始那个 list 写成生成器

yufpga

yufpga   2 小时 11 分钟前

首先生成器的目的并不是为了减少空间占用。其次你要搞明白生成器的原理, 就绕不开理解 yield 的机制。(x for x in [1,5,-1,10]) 等价于:

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

g = gen()

wuwukai007

wuwukai007   2 小时 9 分钟前

@yufpga 你这个也占用内存得啊。

est

est   2 小时 7 分钟前

mylist = [1,5,-1,10]
(x*2 for x in mylist)
(x/2 for x in mylist)


这这种就节约空间了。不用存 3 份。

HashV2

HashV2   2 小时 5 分钟前

@yufpga #2 这种惰性的迭代器不就是为了减少内存占用的么? 不为这个的话是为了什么啊

yufpga

yufpga   1 小时 55 分钟前

@wuwukai007
@HashV2
我并没有在解释节省内存的问题,我在说的是生成器的原理,解释元祖形式的列表生成器的本质。

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

事实上,你们也看到,生成器不一定总是会减少内存占用

yufpga

yufpga   1 小时 52 分钟前

@HashV2 你说的惰性迭代器缺失可以减少内存占用,但生成器的应用场景不只是迭代器上

HashV2

HashV2   1 小时 47 分钟前

@yufpga #7 👌

abersheeran

abersheeran   42 分钟前

你的场景不对。

比如你要处理一个 31Gb 的文件,你电脑却只有 16G 内存,该怎么办呢?这时候用 yield file.read(4096) 进行流式处理。就能大幅度节约内存空间。

BeautifulSoap

BeautifulSoap   27 分钟前

谈生成器不谈迭代器的话你当然搞不清楚这么搞是为什么

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

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


然后就是生成器,生成器可以部分看作是迭代器的语法糖(虽然 yield 作用不止是语法糖),你手写迭代器需要实现__next__()和__iter__()两个接口,而用 yield 构建的生成器只需要简单几行代码就行了,生成器和迭代器一样可以使用 next()迭代,也能用 `for in xxx` 这个语法糖,所以,本质上还是为了方便遍历啊

Lemeng

Lemeng   18 分钟前

路过,学习一下

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK