python中return_【已解决】Python中直接return数组和yield的区别

看到别人代码:def mongoGridfsFiles():

...

client = MongoClient(uri)

db = client.gridfs

collection = db.fs.files

for document in collection.find():

yield document

def main():

db = pymysql.connect(**curMysqlConfigDict)

documents = mongoGridfsFiles()

insertMedia(db, documents)

不太清楚:

为何没有直接用return返回整个数组,而要用yield

且在调试期间注意到:

mongoGridfsFiles没有先执行,而是在后续函数insertMedia中调用到了返回的每个document后,mongoGridfsFiles才执行,才开始产生一个个document并返回

搜:

python return vs yield

想要理解yield,需要先理解generators

以及先要搞清楚:iterables>>> mylist = [1, 2, 3]

>>> for i in mylist:

...    print(i)

1

2

3

以及:>>> mylist = [x*x for x in range(3)]

>>> for i in mylist:

...    print(i)

0

1

4

类似的这种iterable的,比如

lists, strings, files…

等等,缺点是:

所有的值,都要保存到内存中

-》而实际情况下,当数据个数很多时,数据量很大时,我们并不希望所有的值都作为list返回,都放在内存中

Generators是个iterators,是其中一种iterable,你可以每次循环只返回一个值

Generators并不把所有的值都保存在内存中 -》 是实时的,在你用的时候,才产生,生成对应的值:>>> mygenerator = (x*x for x in range(3))

>>> for i in mygenerator:

...    print(i)

0

1

4

注意到此处是(),表示Generator

(之前的[],表示list)

不过Generator没法被(第二次)多次调用,即此处不能再次调用:

for i in mygenerator:

yield

yield,使用方式和return差不多

除了函数本身会返回一个generator>>> def createGenerator():

...    mylist = range(3)

...    for i in mylist:

...        yield i*i

...

>>> mygenerator = createGenerator() # create a generator

>>> print(mygenerator) # mygenerator is an object!

<generator object createGenerator at 0xb7555c34>

>>> for i in mygenerator:

...     print(i)

0

1

4

此处去调试代码,发现的确函数mongoDialogs返回的的确是generator的object:<generator object mongoDialogs at 0x10698dd00>

03c3a5fb7947b7ae916fe48a34f10c69.png

所以,此处通过函数中用yield返回一个generator,满足了如下场景:确定会返回大量的,很多个的数据

且不希望占用内存否则直接return返回数据的list,数据量太大,会占用太多内存

且确保只会使用一次generator只有一条命 -》generator只能用一次,第二次再去调用就无效了

注意:直接调用对应包含了yield的函数时,函数是不会执行的,直到你后期使用到了该(函数返回的)generator时,函数才会真正执行逻辑是,感觉有点点像是delay的逻辑,延迟加载/执行

然后对于后续回复中,有人说的更清楚:

yield没有看起来的那么魔性。

其内部执行逻辑是:

你调用了包含yield的函数时,函数代码没有被执行,只是返回一个generator对象。

当后续你使用generator,去获取一个值时,python解析器才,第一次的,真正的去执行对应的代码,知道碰到第一个yield,返回你要的第一个值,然后暂停该函数的执行(等待下次继续被调用)

后续要返回第二个值时,python解析器再去继续恢复执行yield部分,返回第二个值,再暂停执行;

如此继续。

直到返回所有的值。

此时generator本身也就被消耗殆尽,彻底消失了。

如此而已。

也因此,generator只有一条命,无法被多次重复调用。

【总结】正常的,小批量的数据,直接用普通的list等类型,即可list等类型的数据是保存在内存中的

如果满足如下场景确定会返回大量的,很多个的数据

且不希望占用太多内存且确保只会使用一次generator只有一条命 -》generator只能用一次,第二次再去调用就无效了

举例:比如我此处mongo中dialog有4万多个

如果全部一次性返回成list列表,则会消耗大量内存

且确保只会调用一次generator,用完就无需再用了

再去使用yield:且确保你了解yield的内部工作逻辑

注意事项:直接调用对应包含了yield的函数时,函数是不会执行的直到你后期使用到了该(函数返回的)generator时,函数才会真正执行感觉逻辑点像是delay的逻辑,延迟加载/执行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值