函数—生成器篇

1. 认识和区分可迭代or生成器

1.1 可迭代对象

当你建立了一个列表,你可以逐项地读取这个列表,这叫做一个可迭代对象

当你使用一个列表生成式来建立一个列表的时候,就建立了一个可迭代的对象

所有可以使用  for..in..语法的叫做一个迭代器:例如列表,字符串,文件……

经常使用它们是因为我们可以如愿的读取其中的元素,但是你把所有的值都存储到了内存中,如果你有大量数据的话这个方式并不是你想要的

mylist=[ x*x for x in range(3) ]
for i in mylist:
print(i) for i in mylist:
print(i)
0
1
4
0
1

1.2 生成器

生成器是可以迭代的,但是你只可以读取它一次,因为它并不把所有的值放在内存中,它是实时地生成数据

mygenerator=( x*x for x in range(3) )
for i in mygenerator:
print(i) for i in mygenerator:
print(i) 0
1
4

2. 理解生成器 & yield

2.1 生成器是惰性求值的

惰性求值也叫延迟求值,顾名思义就是表达式不会在它被绑定到变量之后就立即求值,而是等用到时再求值。

延迟求值的一个好处是能够建立可计算的无限列表而没有妨碍计算的无限循环或大小问题。

考虑到yield的特性:可在减少内存占用、避免使用递归等场景时选择yield

2.2  生成器函数的执行流程

# yield关键字的作用是把一个函数变成一个generator,称为生成器函数。
# 生成器函数的返回值是生成器

* 生成器函数执行的时候,不会执行函数体
* 当next生成器的时候, 当前代码执行到之后的第一个yield,会弹出值,并且暂停函数
* 当再次next生成器的时候,从上次暂停处开始往下执行
* 当没有多余的yield的时候,会抛出StopIteration异常,异常的value是函数的返回值

通过以下例子来理解generator执行流程:

def gen(x):
if x!=0:
yield x mygenerator=gen(3) print(mygenerator) #当我们调用这个函数时,我们发现函数内部的代码并不立马执行,而只是返回了一个生成器对象
#<generator object gen at 0x7f63ee065888> for i in mygenerator: #当你使用for进行迭代时,函数内的代码才执行
print(i)
#3 print(next(mygenerator)) #或者使用next()
#3
def gen(max):         # def gen():
a,b=1,1 # do something (a)
while a<max:
yield a # yield a # (b)
a,b=b,a+b # do something (c) for n in gen(15): # for n in gen():
print(n) # do something with n (d)

def dedupe(items):
seen = set()
for item in items:
if item not in seen:
yield item
seen.add(item) a = [1, 5, 2, 1, 9, 1, 5, 10]
for n in dedupe(a):
print(n)
1
5
2
9
10 执行大致过程(个人理解,有误请指正):
        seen=set( )    生成器环境初始化
|
dedupe内的for循环
|
调用yield item=1
|
print 1
|
add 1
|
dedupe内的for循环
|
调用yield item=5
|
print 5
|
add 5
|
dedupe内的for循环
|
调用yield item=2
|
print 2
|
add 2
|
dedupe内的for循环('1'已经在items里所以不执行循环)
|
dedupe内的for循环
|
调用yield item=9
|
......
def gen():
print('a')
yield 1
print('b')
yield 2
return 3 g=gen() print(g)
#<generator object gen at 0x7f144845a308> print(next(g))
#a
#1 print(next(g))
#b
#2 print(next(g))
#StopIteration: 3

3. 生成器作用场景

3.1  计数器的例子

# version-1
def counter():
x=0
while True:
x+=1
yield x def inc(x):
return next(x) # version-2
def counter():
x=0
while True:
x+=1
yield x def inc():
c=counter()
return lambda :next(c) # version-3
def make_inc():
def counter():
x=0
while True:
x+=1
yield x
c=counter()
return lambda :next(c)
## 为什么这里不直接 return next(c) ##
def make_inc():
def counter():
x=0
while True:
x+=1
yield x
c=counter()
return lambda :next(c)
# return lambda:next(c)的运行结果
incr=make_inc()
print(id(incr())) #取1
#8939648
print(id(incr())) #取2
#8939680 def make_inc():
def counter():
x=0
while True:
x+=1
yield x
c=counter()
return next(c)
# return next(c)的运行结果
print(id(make_inc())) #取1
#8939648
print(id(make_inc())) #取1
#8939648

3.2  解决递归问题 — 生成斐波那契数列的例子

def fib(max):
n,a,b=0,0,1
while n<max:
yield b
a,b=b,a+b
n+=1 for n in fib(5):
print(n) 1
1
2
3
5

3.3  协程 —— 生成器的高级用法

进程、线程 ——在内核态调度的
协程 ——在用户态调度(即用户自己写调度器)
——运行在一个线程之内,所以也被叫做轻量线程
——非抢占式调度
调度 ——简单的说就是由调度器来决定哪段代码占用cpu时间 协程在python3已经进入标准库了 ——asyncio
python3.5 中加入了 asyn、 await延伸支持

参考文章

《Python yield使用浅析-廖雪峰(含通过yield实现文件读取的方法)》

《[译]python关键字yield的解释(stackoverflow)》

《python中的惰性求值》

[PY3]——函数——生成器(yield关键字)的更多相关文章

  1. (转) Python Generators(生成器)——yield关键字

    http://blog.csdn.net/scelong/article/details/6969276 生成器是这样一个函数,它记住上一次返回时在函数体中的位置.对生成器函数的第二次(或第 n 次) ...

  2. 理解 ES6 语法中 yield 关键字的返回值

    在 ES6 中新增了生成器函数的语法,本文解释了生成器函数内 yield 关键字的返回值. 描述 根据语法规范,yield 关键字用来暂停和继续执行一个生成器函数.当外部调用生成器的 next() 方 ...

  3. PHP性能优化利器:生成器 yield理解

    如果是做Python或者其他语言的小伙伴,对于生成器应该不陌生.但很多PHP开发者或许都不知道生成器这个功能,可能是因为生成器是PHP 5.5.0才引入的功能,也可以是生成器作用不是很明显.但是,生成 ...

  4. Python:笔记(7)——yield关键字

    Python:笔记(7)——yield关键字 yield与生成器 所谓生成器是一个函数,它可以生成一个值的序列,以便在迭代中使用.函数使用yield关键字可以定义生成器对象. 一个例子 我们调用该函数 ...

  5. PHP 生成器 yield理解

    如果是做Python或者其他语言的小伙伴,对于生成器应该不陌生.但很多PHP开发者或许都不知道生成器这个功能,可能是因为生成器是PHP 5.5.0才引入的功能,也可以是生成器作用不是很明显.但是,生成 ...

  6. py3.0第四天 函数,生成器迭代器等

    1.列表生成式,迭代器&生成器 孩子,我现在有个需求,看列表[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],我要求你把列表里的每个值加1,你怎么实现?你可能会想到2种方式 > ...

  7. ES6学习笔记<三> 生成器函数与yield

    为什么要把这个内容拿出来单独做一篇学习笔记? 生成器函数比较重要,相对不是很容易理解,单独做一篇笔记详细聊一聊生成器函数. 标题为什么是生成器函数与yield? 生成器函数类似其他服务器端语音中的接口 ...

  8. Python:容器、迭代对象、迭代器、生成器及yield关键字

            在了解Python的数据结构时,容器(container).可迭代对象(iterable).迭代器(iterator).生成器(generator).列表/集合/字典推导式(list, ...

  9. day4 内置函数 迭代器&生成器 yield总结 三元运算 闭包

    内置函数: 内置函数 # abs()返回一个数字的绝对值.如果给出复数,返回值就是该复数的模. b = -100 print(b) print(abs(b)) # all() 所有为真才为真,只要有一 ...

随机推荐

  1. solrcloud 搭建资料

    SolrCloud4.9+zookeeper在CentOS上的搭建与安装 http://www.open-open.com/lib/view/open1411307048750.html 官网教程 h ...

  2. SQL LEAD()函数 LAG()函数

    lag ,lead 分别是向前,向后:lag 和lead 有三个参数,第一个参数是列名,第二个参数是偏移的offset,第三个参数是 超出记录窗口时的默认值) SQL> select id,na ...

  3. SQL Server—— 如何创建定时作业

    在做SQL server 管理时,往往需要每日执行定时任务,但是如果每天都去人工执行,非常不方便,而且一般定时操作,都应该是在数据库压力不大时,一般是在夜间.所以我们需要创建定时作业来代替人工的执行定 ...

  4. ansible 之条件语句 when

    注册变量: 变量的另一个用途是将一条命令的运行结果保存到变量中,供后面的playbook使用.例如: - hosts: webservers tasks: - shell: /usr/bin/foo ...

  5. 如何成功导入SlidingMenu库?

    SlidingMenu是一个开源的侧滑菜单(https://github.com/jfeinstein10/SlidingMenu).  为大家的安卓程序提供侧滑菜单,这个功能也非常有用. 要想正常使 ...

  6. 指针版P3690 【模板】Link Cut Tree (动态树)

    题面 传送门 题解 鉴于数组版实在是太慢我用指针版重新写了一遍 代码基本是借鉴了lxl某道关于\(LCT\)的题 //minamoto #include<bits/stdc++.h> #d ...

  7. html实现时间输入框

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Java网络编程以及简单的聊天程序

    网络编程技术是互联网技术中的主流编程技术之一,懂的一些基本的操作是非常必要的.这章主要讲解网络编程,UDP和Socket编程,以及使用Socket做一个简单的聊天软件. 全部代码下载:链接 1.网络编 ...

  9. Linux C 重定向简单范例

    //前言:我们知道printf()会将信息输出到stdout流,然后展示到屏幕上. //那么我们所实现的简单的重定向就可以将stdout指向一个文件,然后读写,这样就达到了重定向的目的. //code ...

  10. STM32-RS485通信软硬件实现

    OS:Windows 64 Development kit:MDK5.14 IDE:UV4 MCU:STM32F103C8T6/VET6 AD:Altium Designer 18.0.12 1.RS ...