Python 基础(十六):迭代器与生成器
1 迭代器
迭代
我们知道 Python 中有一些对象可以通过 for
来循环遍历,比如:列表、元组、字符等,以字符串为例,如下所示:
for i in 'Hello':
print(i)
执行结果:
H
e
l
l
o
这个遍历过程就是迭代。
可迭代对象
可迭代对象需具有 __iter__()
方法,它们均可使用 for
循环遍历,我们可以使用 isinstance()
方法来判断一个对象是否为可迭代对象,看下示例:
from collections import Iterable
print(isinstance('abc', Iterable))
print(isinstance({1, 2, 3}, Iterable))
print(isinstance(1024, Iterable))
执行结果:
True
True
False
迭代器
迭代器需要具有 __iter__()
和 __next__()
两个方法,这两个方法共同组成了迭代器协议,通俗来讲迭代器就是一个可以记住遍历位置的对象,迭代器一定是可迭代的,反之不成立。
-
__iter__()
:返回迭代器对象本身 -
__next__()
:返回下一项数据
迭代器对象本质是一个数据流,它通过不断调用 __next__()
方法或被内置的 next()
方法调用返回下一项数据,当没有下一项数据时抛出 StopIteration
异常迭代结束。上面我们说的 for
循环语句的实现便是利用了迭代器。
我们试着自己来实现一个迭代器,如下所示:
class MyIterator:
def __init__(self):
self.s = '程序之间'
self.i = 0
def __iter__(self):
return self
def __next__(self):
if self.i < 4:
n = self.s[self.i]
self.i += 1
return n
else:
raise StopIteration
mi = iter(MyIterator())
for i in mi:
print(i)
输出结果:
程
序
之
间
2 生成器
生成器是用来创建迭代器的工具,其写法与标准函数类似,不同之处在于返回时使用 yield
语句,关于 yield
,我们在Python 爬虫(六):Scrapy 爬取景区信息中已经作了一些介绍,我们再来熟悉一下:
yield 是一个关键字,作用和 return 差不多,差别在于 yield 返回的是一个生成器(在 Python 中,一边循环一边计算的机制,称为生成器),它的作用是:有利于减小服务器资源,在列表中所有数据存入内存,而生成器相当于一种方法而不是具体的信息,用多少取多少,占用内存小。
生成器的创建方式有很多种,比如:使用 yield
语句、生成器表达式(可以简单的理解为是将列表的 []
换成了 ()
,特点是更加简洁,但不够灵活)。看下示例:
示例 1
def reverse(data):
for i in range(len(data)-1, -1, -1):
yield data[i]
for char in reverse('Hello'):
print(char)
执行结果:
o
l
l
e
H
示例 2
# 列表
lis = [x*x for x in range(5)]
print(lis)
# 生成器
gen = (x*x for x in range(5))
for g in gen:
print(g)
执行结果:
[0, 1, 4, 9, 16]
0
1
4
9
16
参考:
https://docs.python.org/zh-cn/3/tutorial/classes.html#iterators
- Cloudera Manager分发Parcel异常分析
- 如何在Hue中配置Impala的负载均衡
- 35行代码实现千万级别字典的快速去重
- PIMS三个漏洞+里程密最新版V2.3 SQL注入漏洞
- 如何在Redhat7.3安装CDH5.14
- CDSW1.3的新功能
- 如何在Hue中配置HiveServer2的负载均衡
- 如何修改CDH集群的IP地址
- 如何在Kerberos环境的CDH集群部署Livy
- 如何在Kerberos环境下使用Haproxy实现HiveServer2负载均衡
- Hive与Impala的关键字
- 如何通过Livy的RESTful API接口向非Kerberos环境的CDH集群提交作业
- 如何编译Livy并在非Kerberos环境的CDH集群中安装
- Livy,基于Apache Spark的开源REST服务,加入Cloudera Labs
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Go语言(十七) 配置文件库项目
- Python 相对路径问题:“No such file or directory“
- 基于etcd服务发现的overlay跨多宿主机容器网络
- Go语言(十六) 日志项目升级
- PyQt5 技术篇-设置窗口相对桌面位置,按屏幕比例
- Go语言(十五) 反射
- SpringBoot应用跨域访问解决方案
- Spring Boot 2.2都有哪些新变化
- Go语言(十四)日志项目
- 如何在Spring Boot中使用Cookies
- 在SpringBoot中使用flyway管理数据库版本状态
- 使用Spring Data JPA进行数据分页与排序
- 搭建一个高可用负载均衡的集群架构(第二部分)
- 在PyTorch中使用Seq2Seq构建的神经机器翻译模型
- 理解 ECMAScript 规范(1)