一、迭代器

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类型,它们表示一个惰性计算的序列;

集合数据类型如listdictstr等是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学习-迭代器、生成器的更多相关文章

  1. Python学习——迭代器&生成器&装饰器

    一.迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素.迭代器仅 ...

  2. python函数-迭代器&生成器

    python函数-迭代器&生成器 一.迭代器 1 可迭代协议 迭代:就是类似for循环,将某个数据集内的数据可以“一个挨着一个取出来” 可迭代协议: ① 协议内容:内部实现__iter__方法 ...

  3. Python基础-迭代器&生成器&装饰器

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 我现在有个需求,看 ...

  4. Python学习二(生成器和八皇后算法)

    看书看到迭代器和生成器了,一般的使用是没什么问题的,不过很多时候并不能用的很习惯 书中例举了经典的八皇后问题,作为一个程序员怎么能够放过做题的机会呢,于是乎先自己来一遍,于是有了下面这个ugly的代码 ...

  5. 【python】迭代器&生成器

    源Link:http://www.cnblogs.com/huxi/archive/2011/07/01/2095931.html 迭代器 迭代器是访问集合元素的一种方式.迭代器对象从集合的第一个元素 ...

  6. python学习之生成器

    4.6 生成器Generrator ​ 生成器本质就是迭代器.python社区生成器与迭代器是一种. ​ 生成器与迭代器的唯一区别:生成器是我们自己用python代码构建的 4.6.1生成器初识 py ...

  7. python学习------迭代器协议和生成器

    一.递归和迭代 递归:自己调用自己 举例解释:问路   A问B康明网络科技怎么走,B说我不是很清楚,我帮你问问C,C说我也不知道.我问问D,D说 就在兴隆.之后D返回结果给C,C返回结果给B,B返回结 ...

  8. day13 python学习 迭代器,生成器

    1.可迭代:当我们打印 print(dir([1,2]))   在出现的结果中可以看到包含 '__iter__', 这个方法,#次协议叫做可迭代协议 包含'__iter__'方法的函数就是可迭代函数 ...

  9. python学习之- 生成器/迭代器

    列表生成式写法: [ i*2 for i in range(10) ]也可以带函数 [ fun(i) for i in range(10) ] 生成器:一边循环一边计算的机制称为生成器.在常用函数中, ...

随机推荐

  1. js如何使用radio

    <input name="sex" type="radio" value="男" checked="checked" ...

  2. .NETCore Docker实现容器化与私有镜像仓库管理

    一.Docker介绍 Docker是用Go语言编写基于Linux操作系统的一些特性开发的,其提供了操作系统级别的抽象,是一种容器管理技术,它隔离了应用程序对基础架构(操作系统等)的依赖.相较于虚拟机而 ...

  3. 从无到有构建vue实战项目(七)

    十四.Vuex的使用 Vuex是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化.Vu ...

  4. Http协议4个新的http状态码:428、429、431、511;

    1.428 Precondition Required (要求先决条件) 先决条件是客户端发送 HTTP 请求时,必须要满足的一些预设条件.一个好的例子就是 If-None-Match 头,经常用在 ...

  5. unity_实用小技巧(相机跟随两个主角移动)

    在两人对战的游戏中,有时候我们希望能看清楚两玩家的状态,这时我们需要让相机跟随玩家,可是我们不能让相机只跟随一个玩家移动,这时我们可以取两玩家的中点作为相机的位置.方法如下: public Trans ...

  6. 《Java 编写基于 Netty 的 RPC 框架》

    一 简单概念 RPC: ( Remote Procedure Call),远程调用过程,是通过网络调用远程计算机的进程中某个方法,从而获取到想要的数据,过程如同调用本地的方法一样. 阻塞IO :当阻塞 ...

  7. runnable和thread实现多线程的区别

    下面以典型的买票程序(基本都是以这个为例子)为例,来说明二者的区别. 首先通过继承Thread类实现,代码如下: class MyThread extends Thread{ private int ...

  8. js多重数组完全展开

    有时候项目中会遇到多重数组,需要判断多重数组里面有没有要找的对象,强大的js就可以帮助我们 var arrTest = [1, [2, 3, [4]], 5, 6, [7, 8], [[9, [10, ...

  9. Nacos高可用集群解决方案-Docker版本

    文章主旨 本文目的是配置高可用的Nacos集群 架构图 整体架构为:Nginx + 3 x Nacos +高可用MySQL 高可用MySQL使用主从复制结构的可以参考Docker搭建MySQL主从集群 ...

  10. Linux下手动安装MySQL5.7

    1.下载tar包,这里使用wget从官网下载 https://dev.mysql.com/downloads/mysql/ 2.将mysql安装到/usr/local/mysql下 # 解压 tar ...