Python学习-迭代器、生成器
一、迭代器
1. 可迭代对象
我们知道字符串、列表、元组、字典、集合都可以使用for语句进行循环遍历,然后输出每一个元素,这些都是可迭代对象。
检查对象是否是可迭代对象可以用两种方式去判断:
(1)使用dir()查看对象包含的方法和函数, 如果能找到__iter__, 那么这个对象就是一个可迭代对象
>>> lst = ['a', 'b', 'c']
>>> dir(lst) #查看对象包含的方法和函数
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> dir(list) #查看类中声明的方法和函数
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>>
(2)使用isinstance进行判断
>>> from collections import Iterable
>>> lst = ['a', 'b', 'c']
>>> isinstance(lst, Iterable) #结果为True,为可迭代对象
True
iterable翻译: 可迭代的; 可重复的; 迭代的
此处只查看了列表类型对象, 其他类型的对象可以自己尝试.
2. 迭代器
概念: 可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
所谓的迭代器就是具有next方法的对象. 在调用next方法时, 迭代器会返回它的下一个值. 如果next方法被调用, 但迭代器没有值可以返回, 就会引发一个StopIteration异常.
迭代器和可迭代对象有什么区别:
(1) 可迭代对象不一定是迭代器, 但迭代器一定是可迭代对象
(2) 可迭代对象有iter方法, 迭代器有iter和next方法; 可以使用iter方法将可迭代对象转为迭代器
(3) 迭代器是惰性的, 只有当你使用next方法去取值的时候, 它才会返给你一个值
判断对象是否是迭代器:
>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance(['a', 'b'], Iterator)
False
>>> isinstance('hello', Iterator)
False >>> g = (x * 2 for x in range(5))
>>> isinstance(g, Iterator)
True
>>> next(g)
0
>>> next(g)
2
>>> next(g)
4
>>> next(g)
6
>>> next(g)
8
>>> next(g) # 没有值返回时, 抛出异常StopIteration
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
>>>
使用iter方法(或__iter__)将对象变为迭代器:
>>> lst = ['a', 'b', 'c']
>>> isinstance(lst, Iterator)
False
>>> lst_g = lst.__iter__()
>>> isinstance(lst_g, Iterator)
True
>>> for ele in lst_g:
... print(ele)
...
a
b
c
>>> dic = {'a': 1, 'b': 2}
>>> isinstance(dic, Iterator)
False
>>> dic_g = iter(dic)
>>> isinstance(dic_g, Iterator)
True
小结:
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
二、生成器
1. 先介绍一下列表生成式 (内容粘贴自廖雪峰老师的官方网站)
列表生成式,是Python内置的非常简单却强大的可以用来创建list的生成式。
列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。
举个例子,要生成list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]可以用list(range(1, 11)):
>>> list(range(1, 11))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
但如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么做?方法一是循环:
>>> L = []
>>> for x in range(1, 11):
... L.append(x * x)
...
>>> L
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
但是循环太繁琐,而列表生成式则可以用一行语句代替循环生成上面的list:
>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
写列表生成式时,把要生成的元素x * x放到前面,后面跟for循环,就可以把list创建出来,十分有用,多写几次,很快就可以熟悉这种语法。
for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:
>>> [x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]
还可以使用两层循环,可以生成全排列:
>>> [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
2. 生成器
通过列表生成式我们可以快速创建一个列表,这种方法生成列表,它会一次性的返回给我们全部元素,想想如果列表包含100万个元素,一次性返回会占用很大的内存空间,如果我们仅仅需要访问前面几个元素,这种方式生成的列表就比较浪费内存空间了。有没有一种方式,按照我们的需要,访问时给我们返回元素,不要像列表生成式一样一次全部返回。生成器就可以满足我们的这种需求,按需返回,可以调用next方法,生成器会返回它的下一个值,当没有值可以返回时,抛出StopIteration异常。实际使用中,我们一般使用for循环对生成器进行迭代。
在python中创建生成器:
(1)生成器函数
def func():
print('hello world')
yield 'world' #与定义的普通函数没有区别,只是含有yield关键字;函数中包含yield关键字即为生成器函数
print('hello china')
yield 'china' g = func()
print(next(g))
print(next(g))
print(g)
# 输出结果
hello world
world
hello china
china
<generator object func at 0x108ad3468>
(2)生成器表达式
只要把一个列表生成式的[]改成(),就创建了一个generator。
g = (x * x for x in range(5))
print(g)
for i in g:
print(i)
输出结果:
<generator object <genexpr> at 0x10a845468>
0
1
4
9
16 lst = ['a', 'b', 'c', 'd']
g2 = (x * 2 for x in lst)
print(g2)
while 1:
try:
print(next(g2))
except StopIteration:
break
输出结果:
<generator object <genexpr> at 0x10395b468>
aa
bb
cc
dd
Python学习-迭代器、生成器的更多相关文章
- Python学习——迭代器&生成器&装饰器
一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...
- python函数-迭代器&生成器
python函数-迭代器&生成器 一.迭代器 1 可迭代协议 迭代:就是类似for循环,将某个数据集内的数据可以“一个挨着一个取出来” 可迭代协议: ① 协议内容:内部实现__iter__方法 ...
- Python基础-迭代器&生成器&装饰器
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...
- Python学习二(生成器和八皇后算法)
看书看到迭代器和生成器了,一般的使用是没什么问题的,不过很多时候并不能用的很习惯 书中例举了经典的八皇后问题,作为一个程序员怎么能够放过做题的机会呢,于是乎先自己来一遍,于是有了下面这个ugly的代码 ...
- 【python】迭代器&生成器
源Link:http://www.cnblogs.com/huxi/archive/2011/07/01/2095931.html 迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素 ...
- python学习之生成器
4.6 生成器Generrator 生成器本质就是迭代器.python社区生成器与迭代器是一种. 生成器与迭代器的唯一区别:生成器是我们自己用python代码构建的 4.6.1生成器初识 py ...
- python学习------迭代器协议和生成器
一.递归和迭代 递归:自己调用自己 举例解释:问路 A问B康明网络科技怎么走,B说我不是很清楚,我帮你问问C,C说我也不知道.我问问D,D说 就在兴隆.之后D返回结果给C,C返回结果给B,B返回结 ...
- day13 python学习 迭代器,生成器
1.可迭代:当我们打印 print(dir([1,2])) 在出现的结果中可以看到包含 '__iter__', 这个方法,#次协议叫做可迭代协议 包含'__iter__'方法的函数就是可迭代函数 ...
- python学习之- 生成器/迭代器
列表生成式写法: [ i*2 for i in range(10) ]也可以带函数 [ fun(i) for i in range(10) ] 生成器:一边循环一边计算的机制称为生成器.在常用函数中, ...
随机推荐
- Git安装与使用(windows环境)(一)----Git安装、生成公钥和私钥、添加SSH
安装 1.从官网下载git:http://git-scm.com/downloads 2.安装git,选择git组件安装,如下图 3.一直next,直到出现下面的窗口.这里是选择命令行形式.(可以理解 ...
- SpringBoot读取配置文件源码探究
1. SpringBoot读取配置文件源码探究 1.1. 概览 springboot的源码是再原来的Spring源码上又包了一层,看过spring源码都知道,当我们从入口debug进去的时候,原来的S ...
- Codeforces 396D
题意略. 思路: 很经典的逆序对计数问题. https://blog.csdn.net/v5zsq/article/details/79006684 这篇博客讲得很好. 当循环到n的时候,我们需要特殊 ...
- 命令行通过入参调用jar包
命令行通过入参调用jar包 最近因为项目需要,需要实现一个功能,即定时执行服务器上的一个脚本去对数据库的数据进行业务处理,要操作的数据库有很多种,mysql.db2.oracle.sqlserver等 ...
- Python Web Flask源码解读(二)——路由原理
关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...
- Joda学习笔记
Joda Time简介 日常业务开发中,经常需要处理日期.比如:获取当前一个月之内的开播记录,获取十分钟之内的红包记录等等.我们之前是用java.util.Calendar实现的,直到我看到占小 ...
- Linux中mysql5.7主从配置
MySQL主从配置(两台Linux之间) 简介 Linux下MySQL数据库的主从同步用来实现读写分离.主数据库进行数据的插入,删除与更新:从数据库专门用来查询操作,缓解数据库的压力.让运行海量数据的 ...
- iOS中的几个重要方法
iOS开发中几个重要的方法: 加载类到内存,程序刚启动的时候调用,调用在main函数之前 1.+(void)load{ } 初始化类,类第一次使用的时候调用一次 2.+(void)initialize ...
- hdu-6621 K-th Closest Distance
题目链接 K-th Closest Distance Problem Description You have an array: a1, a2, , an and you must answer ...
- CF - 1108 F MST Unification
题目传送门 题意:在一幅图中, 问需要使得多少条边加一,使得最小生成树只有一种方案. 题解:Kruskal, sort完之后,对于相通的一个边权w,我们可以分析出来有多少边是可以被放到图里面的,然后我 ...