一、迭代器

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. DBUtils框架的使用(下)

    刚才讲了使用QueryRunner插入.修改.更新数据,现在来学习一下使用QueryRunner进行数据库表查询. 通过QueryRunner类的query()方法即可完成数据库表的查询操作,但是在查 ...

  2. Keras实例教程(1)

    https://blog.csdn.net/baimafujinji/article/details/78384792

  3. 内容协商在视图View上的应用【享学Spring MVC】

    每篇一句 人生很有意思:首先就得活得长.活得长才能够见自己,再长就可以见众生 前言 在经过 前两篇 文章了解了Spring MVC的内容协商机制之后,相信你已经能够熟练的运用Spring MVC提供的 ...

  4. js遍历API总结

    1.for 循环 普通遍历方法,可优化,存下数组的length,避免每次都去获取数组的length,性能提升 2.for-in 可遍历数组和对象, (for key in obj){} 该方法既可以读 ...

  5. 你知道JavaScript这六种错误类型吗?

    前言 今日话题,了解JavaScript的错误处理机制. 一.ReferenceError 引用一个不存在的变量时发生的错误.将一个值分配给无法分配的对象,比如对函数的运行结果或者函数赋值. 举栗子 ...

  6. 通过代码审计找出网站中的XSS漏洞实战(三)

    一.背景 笔者此前录制了一套XSS的视频教程,在漏洞案例一节中讲解手工挖掘.工具挖掘.代码审计三部分内容,准备将内容用文章的形式再次写一此,前两篇已经写完,内容有一些关联性,其中手工XSS挖掘篇地址为 ...

  7. 牛客小白月赛4 B 博弈论 思维 字符串

    链接:https://www.nowcoder.com/acm/contest/134/B来源:牛客网 题目描述 铁子和顺溜在学习了博弈论的sg函数之后,解决了很多很多博弈题,现在他们遇到了一道难题. ...

  8. CF940A Points on the line 思维

    A. Points on the line time limit per test 1 second memory limit per test 256 megabytes input standar ...

  9. GNU大型项目构建和覆盖率生成(第一篇)

    目录 0. 序言 1. 项目描述 2. 项目构建 2.1 编译规则 2.2 构建过程 3. 覆盖率分析 0. 序言 在开始正文之前,请允许我先说明一下本文的目的和写作的动机,好让读者不惑. 我们知道, ...

  10. Python 单元测试框架系列:聊聊 Python 的单元测试框架(一):unittest

    作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...