Python中幽灵般的yield

Python中幽灵般的yield

Python语言容易上手,偶尔也容易伤手,比如yield的用法。

这篇短文希望用简单的例子把yield的本质讲清楚,只是希望而已,万一讲不清楚,你可以用红包砸我~,:-x
直接说本文最重要的一句话:

python函数定义里用了yield就会把函数变为生成器。
例子#1 - 正常函数定义、调用

代码 try.py:
定义一个函数func,然后调用它,该函数返回1

#!/usr/bin/env python

def func():
    print ("func() started")
    return 1
    print ("func() ended")

g = func()
print "g = ", g

输出结果:

$ ./try.py
func() started
g =  1

这个没什么需要解释的。

例子#2 - 把例子#1里函数定义的return改成yield
#!/usr/bin/env python

def func():
    print ("func() started")
    yield 1
    print ("func() ended")

g = func()
print "g = ", g

输出结果:

$ ./try.py
g =  <generator object func at 0x10ccbcaa0>
  • 发现没?func这个“函数”竟然没有被调用!func的返回结果g的类型变成了生成器(generator)对象。

  • 因为“函数”func的定义里用了yield,导致func的类型不再是函数,而是变成了生成器类型定义,这时候“调用”func等于创建一个generator对象g,并不会执行里面的代码。

说明:
  • “函数定义”里一旦用了yield,就不再表示定义函数,而是变成定义生成器类型。这是动态类型语言python的特点。
  • 另外,“函数”定义里有return语句就是函数,有yield就是生成器,return和yield不能同时使用,要么你是定义函数,要么你是定义生成器,只能二选一。

  • 理解了yield必然导致生成器,就抓住了yield的本质,要运行生成器func里的代码就必须对它的对象进行遍历。

  • 生成器是只能遍历一次的迭代器,而常用的列表是可以重复从头多次遍历的,生成器遍历到尾部就不能再从头遍历了。

最后例子 - 遍历yield定义的生成器
#!/usr/bin/env python

def func():
    print ("func() started")
    for i in range(0,3):
        yield i #每次到这里都生成一个迭代元素
    print ("func() ended")

g = func() #这里不会执行func里的代码,只是创建了一个对象(generator对象)
print "g = ", g
for val in g: #遍历生成器,执行func里生成一个个迭代元素的代码,等价于执行了func里面的代码
    print "    val=", val

输出结果:

$ ./try.py
g =  <generator object func at 0x10a6e2aa0>
func() started
    val= 0 #生成的一个元素
    val= 1 #生成的一个元素
    val= 2 #生成的一个元素
func() ended #遍历的时候扫过这一行,所以它执行到了,但是它后面没有生成的元素了,到尾部了
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值