Python中幽灵般的yield

原创 2016年08月28日 22:09:07

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 #遍历的时候扫过这一行,所以它执行到了,但是它后面没有生成的元素了,到尾部了

关于“幽灵按钮”的一些事

最近,扁平化UI越来越充斥在我们的生活中,应用了扁平化UI设计思想的东西也是随处可见,而在这种大环境下一个新的名词也就应运而生了:幽灵按钮(Ghost Buttons)。 幽灵按钮应当算得上是网页前...
  • u010571913
  • u010571913
  • 2015年01月10日 20:27
  • 1352

十二、Python的yield用法与原理

翻了一篇workflow上关于yield的用法,翻的有点烂,在这里贻笑大方了,慢慢来,总是期待着一点一点的进步。 为了理解yield的机制,我们需要理解什么是生成器。在此之前先介绍迭代器iter...
  • alvine008
  • alvine008
  • 2015年02月02日 16:21
  • 42861

浅谈Python中的yield表达式

浅谈Python协程中的yield表达式python生成器python中生成器是迭代器的一种,使用yield返回函数值。每次调用yield会暂停,而可以使用next()函数和send()函数可以恢复生...
  • u014683535
  • u014683535
  • 2016年06月25日 11:26
  • 2387

利用 Python yield 创建协程将异步编程同步化

利用 Python yield 创建协程将异步编程同步化 Python 2015-09-07 08:40:34 发布 您的评价: 0.0 收藏 0收藏 在 Lua 和 Pyt...
  • a675311
  • a675311
  • 2016年11月14日 17:57
  • 398

Python yield使用浅析

初学 Python 的开发者经常会发现很多 Python 函数中用到了 yield 关键字,然而,带有 yield 的函数执行流程却和普通函数不一样,yield 到底用来做什么,为什么要设计 yie...
  • jkhere
  • jkhere
  • 2013年11月27日 10:34
  • 582

Python中yield的用法

生成器:一个函数调用时返回一个迭代器,则就叫这个函数为一个生成器。生成器与普通函数的区别是生成器中用到可yield。yield的概念1、如何生成斐波那契数列斐波那契(Fibonacci)数列是一个非常...
  • zcaijin
  • zcaijin
  • 2016年07月06日 15:32
  • 156

Python yield 使用浅析(作者:廖雪峰)

初学 Python 的开发者经常会发现很多 Python 函数中用到了 yield 关键字,然而,带有 yield 的函数执行流程却和普通函数不一样,yield 到底用来做什么,为什么要设计 yiel...
  • Artprog
  • Artprog
  • 2016年08月25日 11:40
  • 889

关于Python生成器(Generator的yield、next、send)

习惯了C++和Java等强类型的语言,函数调用都是顺序执行的,返回之后栈清空,不留痕迹。初次遇到Python生成器,理解起来,真是破费周章。 关于Python生成器,大概需要关心的主要是yield...
  • ycf74514
  • ycf74514
  • 2015年10月10日 01:24
  • 819

关于Python中的yield

在介绍yield前有必要先说明下Python中的迭代器(iterator)和生成器(constructor)。 一、迭代器(iterator) 在Python中,for循环可以用于Python中的...
  • chencheng126
  • chencheng126
  • 2015年12月03日 15:34
  • 368

提高你的Python: 解释yield’和Generators(生成器)

在开始课程之前,我要求学生们填写一份调查表,这个调查表反映了它们对Python中一些概念的理解情况。一些话题("if/else控制流" 或者 "定义和使用函数")对于大多数学生是没有问题的。但是有一些...
  • cn_wk
  • cn_wk
  • 2016年05月04日 17:59
  • 786
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Python中幽灵般的yield
举报原因:
原因补充:

(最多只允许输入30个字)