**生成器 (generator)**
在 Python 中一边循环一边计算的方式称为生成器 ( generator )。
当我们需要使用无穷无尽的数据的时候,由于电脑机器的内存是有限的,不可能一次性存储那么多的数据,我们就可以根据某种规律计算出下一个数据的值,我们只需保存算法,这样就节省大量的空间,而不需要保存真实的海量数据,再在循环中不断推算下一个数据值的思想就诞生了生成器 ( generator )。
**生成器的创建常用方法**
方法一:把一个列表生成式的 [ ] 改成 ( ),就创建了一个生成器 ( generator )。
~~~
>>> _list = [ i for i in range(3)]
>>> _list
[0, 1, 2]
>>> gene = (i for i in range(3))
>>> gene
<generator object <genexpr> at 0x7f495742a6d0>
~~~
使用列表生成式生成的列表我们可以直接打印出列表中的每一个元素,但是生成的生成器对象我们却只得到了一个内存地址,那如何获取生成器对象中的元素呢?
通过 next() 方法打印生成器中的元素,直到最后抛出 StopIteration 错误表示无法继续返回下一个值了。
~~~
>>> next(gene)
0
>>> next(gene)
1
>>> next(gene)
2
>>> next(gene) #抛出 StopIteration 错误
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
~~~
当然我们也可以使用 for 循环打印生成器中的元素
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
gene = (i for i in range(3))
for i in gene:
print(i)
~~~
方法二:在函数定义中使用了 yield 关键字,那么这个函数就不再是一个普通函数,而是一个生成器 ( generator )。
生成器 ( generator ) 和普通函数的执行流程不一样。函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而生成器 ( generator ) 的函数,在每次调用 next() 的时候执行,遇到 yield 语句返回,再次执行时从上次返回的 yield 语句处继续执行 , 更简单点理解生成器就是一个迭代器。
**实例说明**
~~~
>>>def info():
... print('Python')
... yield 1
... print('PHP')
... yield 2
... print('Java')
... yield 3
...
~~~
调用时,首先要生成一个生成器 ( generator ) 对象,然后用 next() 函数不断获得下一个返回值:
~~~
>>> g = info()
>>> next(g) #第一次调用
Python
1
>>> next(g) #第二次调用
PHP
2
>>> next(g) #第三次调用
Java
3
>>> next(g) #抛出 StopIteration 错误
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
~~~
可以看出, info() 已经不是一个普通函数而是生成器,在调用过程中遇到 yield 就中断,下次又在中断出继续执行。执行 3 次 yield 后,已经没有 yield 可以执行了,所以,第 4 次调用 next(g) 就抛出 StopIteration 的错误。
实例使用 yield 实现斐波那契数列
~~~
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
def fibonacci(n): # 斐波那契生成器函数
a, b, num = 0, 1, 0
while True:
if (num > n):
return
yield a
a, b = b, a + b
num += 1
g = fibonacci(3) # g是一个由斐波那契生成器函数返回迭代器
while True:
try:
print (next(g), end=",")
except StopIteration:
break
~~~
执行结果
~~~
0,1,1,2,
~~~
当然在实际开发中我们很少使用 while 去循环迭代器,因为使用 for 进行迭代更方便。
- 跟老司机学Python
- 了解Python
- 1、python简介
- 2、Python发展史
- 3、Python特点
- 4、Python解释器
- 入坑Python
- 1、Python环境搭建
- 2、设置环境变量
- 3、开始使用Python
- 4、运行Python程序
- 掌握Python基础
- Python基础知识
- Python运算符
- 算术运算符
- 比较运算符
- 赋值运算符
- 逻辑运算符
- 位运算符
- 成员运算符
- 身份运算符
- 运算符优先级
- Python的变量与常量
- Python数据类型
- Number数值
- String字符串
- List列表
- Tuple元组
- Dictionary字典
- Set集合
- Python流程控制语句
- 条件判断
- 循环控制
- Python函数
- 1、函数是什么
- 2、函数的定义
- 3、函数的参数
- 4、函数的调用
- 5、嵌套函数
- 6、递归函数
- 7、匿名函数
- 8、函数式编程
- 9、高阶函数
- 1、map
- 2、reduce
- 3、filter
- 4、sorted
- 10、返回函数
- 11、偏函数
- Python文件IO操作
- 标准输入输出
- 读写文件
- with读写文件
- Python高级特性
- 1、列表生成式
- 2、迭代器
- 3、生成器
- 4、装饰器
- Python模块初探
- 1、模块与包
- 2、创建模块
- 3、模块中的作用域
- 4、模块的导入
- Python面向对象编程
- 类与对象
- 类的定义及使用
- 面向对象特性
- 类中的访问域
- 查看对象详情
- Python面向对象进阶
- 类中的方法
- 类中的特殊成员
- 限制对象的属性
- 再聊多继承
- 装x式创建类
- 创建元类
- Python内置模块
- os模块
- sys模块
- random模块
- time模块
- datetime模块
- shutil模块
- collections模块
- base64模块
- json模块
- hashlib模块
- xml模块
- 1. SAX解析XML
- 2. DOM解析XML
- 3. ElementTree解析XML
- urllib模块
- logging模块
- re模块
- Python第三方模块
- Pillow与PIL
- Requests
- Tablib
- Xpinyin
- Chardet
- Pycurl
- Virtualenv
- Python操作数据库
- Mysql操作
- Sqllite操作
- Mongodb操作
- Redis操作
- Python的GUI编程
- Python中GUI的选择
- Tkinter
- wxPython
- Socket网络编程
- Socket网络编程简聊
- Socket内建方法
- TCP协议编程
- UDP协议编程
- TCP与UDP
- Python电子邮件
- SMTP发邮件
- POP3收邮件
- IMAP收邮件
- 进程线程
- 进程与线程
- 进程编程
- 使用进程池
- 进程间的通信
- 线程编程
- 使用线程锁
- Python的GIL
- Web编程
- WSGI介绍
- Web框架
- Flask使用
- 模板jinjia2使用
- 项目结构规划
- 异步与协程
- 概念扫盲
- 异步IO进化之路
- 协程是什么
- yield协程编程
- yield from
- asyncio
- async与await
- aiohttp之client
- aiphttp之server
- 网络爬虫
- 网络爬虫简聊
- Beautiful Soup模块的使用
- pyquery 模块的使用
- selenium模块的使用
- 爬取段子实例
- 错误与调试
- 错误
- 错误处理
- 抛出错误
- 高效的调试
- Python重要语句
- pass语句
- return语句
- Python开发必知
- pip使用详解
- 如何对列表进行迭代
- 如何对字典进行迭代
- 字符串格式化
- 知识扩展
- 网络模型
- GUI是什么