关闭

Python中幽灵般的yield

标签: pythonyield
65人阅读 评论(0) 收藏 举报
分类:

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
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:248次
    • 积分:33
    • 等级:
    • 排名:千里之外
    • 原创:3篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档