迭代器

可迭代对象

遵守可迭代协议的就是可迭代对象,例如:字符串,list dic tuple set都是可迭代对象
或者说,能被for循环的都是可迭代对象
或者说,具有对象.__iter__方法的都是可迭代对象

print(list.__iter__([1,2,3]))
print(dict.__iter__({1:2,3:4}))
print(tuple.__iter__((1,2,3,4)))
print(range.__iter__(range(10)))
运行结果
<list_iterator object at 0x0000023C28DE8710>
<dict_keyiterator object at 0x0000023C28DC6868>
<tuple_iterator object at 0x0000023C28DE8710>
<range_iterator object at 0x00000109ABB3BF30>    

迭代器

遵守迭代器的协议(规则)
必须具备 __iter__ 方法和 __next__方法 两者都有,才是迭代器
迭代器的特性
迭代器不能回退
它是由惰性的
是只执行一次
举个例子

lst = [1,2,3,4]
l1 = lst.__iter__()  #转换成迭代器
print(l1.__next__()) #执行迭代器
print(l1.__next__())
print(l1.__next__())
print(l1.__next__())
运行结果:
1
2
3
4
for循环就是一个迭代器(for 它的执行机制如下)

lst = [1,2,3,4]
count = 0
l = lst.__iter__()
while count < len(lst):
    print(l.__next__())
    count += 1
运行结果: #这就是for循环的运行结果
1
2
3
4
大家可能发现一个问题

lst = [1,2,3,4]
l1 = lst.__iter__()  #转换成迭代器
print(l1.__next__()) #执行迭代器
print(l1.__next__())
print(l1.__next__())
print(l1.__next__())
print(l1.__next__())
print(l1.__next__())
lst共有4个元素,当我在执行的时候多加了几个,它就会报错,那既然for循环也是这样的机制为啥它不报错呢?,这里用到一个知识点,叫捕捉错误
while True:
    try:
        lst = [1,2,3,4]
        l1 = lst.__iter__()  #转换成迭代器
        print(l1.__next__()) #执行迭代器
        print(l1.__next__())
        print(l1.__next__())
        print(l1.__next__())
        print(l1.__next__())
        print(l1.__next__())
    except  StopIteration: #如果知道是什么类型的错误,可以添加
            break
如何判断它是不是迭代器或者是不是可迭代对象呢?

from collections import Iterable,Iterator
lst = [1,2,3,4]
print(isinstance(lst,Iterable))
print(isinstance(lst,Iterator))
print(isinstance(lst.__iter__(),Iterable))
print(isinstance(lst.__iter__(),Iterator))
print(isinstance({1:2,3:4,5:6},Iterable))
print(isinstance({1:2,3:4,5:6},Iterator))
返回结果:
True
False
True
True
True
False

生成器

生成器表达式:

(结果 for 变量量 in 可迭代对象 if 条件筛选)

生成器表达式可以直接获取到⽣成器对象. ⽣成器对象可 以直接进行for循环. ⽣成器具有惰性机制. 
什么是生成器
函数体中存在yield,就是生成器
可以自己定义一些逻辑的
先来举个例子
我们平常上班的时候都比较忙,没时间逛超市,所以一到周末的时候就会去超市把一星期的菜都买好,放冰箱里,这样就不用天天去超市那么麻烦了,但是冰箱里都被放满了,想放点其他的又比较费劲,我们就在想如果能让邻居的大妈每天去买菜的时候给我们带一份是不是很好,那就是如果明天需要做饭就在前一天晚上告诉大妈明天给带一份就可以了,这个就有点类似于生成器的功能,只有在告诉它的时候才会触发.

生成器的执行顺序

def func(): #第1步定义名称
    print(1) #第5步 执行生成器
    yield 4 #第6步 返回执行结果并打印出来,执行到这里停止
    print(2)#第8步 执行生成器
    yield 5 #第9步 返回结果并打印出来
g = func() #第2步,执行,当方向代码块中有yield时,识别为生成器,
执行第3步 g = func()赋给变量g
print(g.__next__())#第4步第一次调用生成器
print(g.__next__())#第7步第二次调用生成器
运行结果:
1
4
2
5
看到上面这个例子,有的人会说,这样也太麻烦了吧,我执行一次就的在下面写一个print(g.__next__()),并不好用,我们都知道for循环的原理就是生成器,那我们可以把多次执行利用for循环来实现

def gen():
    li = []
    for i in range(10):
        yield i
g = gen()
print(g.__next__())#这样是不是很麻烦
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
def gen():
    li = []
    for i in range(10):
        yield i
g = gen()
for i in range(10):
        print(g.__next__())#利用for 循环,很方便的执行

send()

我们在生成器执行时,除了使用next之外,还可以使用send()方法

def func():
    print(44)
    l = yield 5
    print(55)
    print(l)
    yield 3
g = func()
print(g.__next__())
print(g.send('你好啊'))
#相对于 __next__ + 赋值(既能执行下一步操作,又能把值带进去
打印结果:
1
4
2
5
44
5
55
你好啊
3
def gen(x):
    res = 0
    for i in range(x):
        res = yield res ** 2
g = gen(5)
g.send(None)
print(g.send(1))
print(g.send(2))
print(g.send(3))
print(g.send(4))

生成器总结

1生成器具有延迟的作用
生成器其实就是变异的函数,格式和内容都跟函数类似,我们都知道,当我们执行函数的时候,只要函数名+()就会直接执行,但是生成器却不是这样的,它需要执行__next__的时候才会执行,如果不进行此操作,生成器就不会起作用,跟我在例子说到的一样,用的时候才会调用.
2.生成器可以记录位置和结果
当我们执行调用生成器的时候,遇到yield时,它会记录位置,并且可以返回一个结果,等我们下一次再进行调用时,直接从上一次的位置开始执行下面的.
3.生成器节约内存空间
我们如果想获取1个列表中的上万条数据,那首先得先把列表拿出来,然后再进行循环过滤等等,但我们不会一次性获取所有的,只是一部分,如果这么做就太浪费内存了,如果我们使用生成器,可以要什么调什么,岂不是很好.
4.生成器中next执行和yield要一一对应

推导式

列表推导式

li = []
for i in range(10):
    li.append(i)
print(li)
li = [i for i in range(10)] #列表推导式
print(li)
打印结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

列表筛选

li = [i for i in range(10)if i > 3]
print(li)

li = [i for i in range(10)if i % 2 == 0]
print(li)

集合推导式

dic = {1:2,3:4}
se = {i for i in dic.items()}
print(se)
输出结果:
{(1, 2), (3, 4)}

推导过程

dic = {1:2,3:4}
se = set()
for i in dic.items():
    se.add(i)
print(se)
打印结果:
{(1, 2), (3, 4)}

字典推导式

lst = [1,3]
lst1 = [2,4]
dic = {lst[i]:lst1[i] for i in range(2)}
print(dic)
输出结果:
{1: 2, 3: 4}

推导过程

lst = [1,3]
lst1 = [2,4]
dic = {}
for i in range(2):
    dic[lst[i]] = lst1[i]
print(dic)
输出结果:
{1: 2, 3: 4}

生成器推导式

跟元组很相似,但是元组没有推导式,这个是生成器的推导式

l = (i for i in range(100))
for i in range(10):
    print(l.__next__())

推导过程

def func():
    for i in range(10):
        yield i
l = func()
for i in range(10):
    print(l.__next__())

Python之路-迭代器 生成器 推导式的更多相关文章

  1. python之路---12 生成器 推导式

    三十.函数进阶 1.生成器    函数中有yield 的就是生成器函数(替代了return) 本质就是迭代器   一个一个的创建对象     节省内存 ①创建生成器       最后以yield结束 ...

  2. 记录我的 python 学习历程-Day12 生成器/推导式/内置函数Ⅰ

    一.生成器 初识生成器 生成器的本质就是迭代器,在python社区中,大多数时候都把迭代器和生成器是做同一个概念. 唯一的不同就是: 迭代器都是Python给你提供的已经写好的工具或者通过数据转化得来 ...

  3. python迭代器,生成器,推导式

    可迭代对象 字面意思分析:可以重复的迭代的实实在在的东西. list,dict(keys(),values(),items()),tuple,str,set,range, 文件句柄(待定) 专业角度: ...

  4. 12.Python略有小成(生成器,推导式,内置函数,闭包)

    Python(生成器,推导式,内置函数,闭包) 一.生成器初始 生成器的本质就是迭代器,python社区中认为生成器与迭代器是一种 生成器与迭代器的唯一区别,生成器是我们自己用python代码构建成的 ...

  5. Python进阶(四)----生成器、列表推导式、生成器推导式、匿名函数和内置函数

    Python进阶(四)----生成器.列表推导式.生成器推导式.匿名函数和内置函数 一丶生成器 本质: ​ 就是迭代器 生成器产生的方式: ​ 1.生成器函数

  6. Python——生成器&推导式

    生成器 生成器的本质就是迭代器,那么还为什么有生成器呢,两者唯一的不同就是迭代器都是Python给你提供能够的已经写好的工具或者通过数据转化得来的.而生成器是需要我们自己用Python代码构建的工具. ...

  7. Python函数04/生成器/推导式/内置函数

    Python函数04/生成器/推导式/内置函数 目录 Python函数04/生成器/推导式/内置函数 内容大纲 1.生成器 2.推导式 3.内置函数(一) 4.今日总结 5.今日练习 内容大纲 1.生 ...

  8. Python之路迭代器协议、for循环机制、三元运算、列表解析式、生成器

    Python之路迭代器协议.for循环机制.三元运算.列表解析式.生成器 一.迭代器协议 a迭代的含义 迭代器即迭代的工具,那什么是迭代呢? #迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的 ...

  9. python 列表推导式,生成器推导式,集合推导式,字典推导式简介

    1.列表推导式multiples = [i for i in range(30) if i % 2 is 0]names = [[],[]]multiples = [name for lst in n ...

随机推荐

  1. 牛客练习赛42B(异或的性质)

    传送门 b^ c >= b - c,这个结论应该记住,我还在这里证过…… 这个题就用到了这个结论,假如当前答案集合为S,和为a,异或和为b,当前答案为a+b了.这时又读入个c,该不该加进来?a ...

  2. E. 打击判定 判断矩形是否相交

    有一个很明显的做法就是判断PointInPolygon .枚举第二个矩形的点,是否在第一个矩形内,但是有bug 就是那种第二个矩形很大的那种,所以容易想到又枚举第一个矩形的点,看是否在第二个矩形里. ...

  3. shell脚本由基础变量及特殊变量($@、$*、$#等)到实战。

    一.shell脚本建立: shell脚本通常是在编辑器(如vi/vim)中编写,也可以在命令行中直接执行: 1.脚本开头:     规范的脚本第一行需要指出有哪个程序(解释器)来执行脚本中的内容,在L ...

  4. Spring Security LDAP简介

    1.概述 在本快速教程中,我们将学习如何设置Spring Security LDAP. 在我们开始之前,了解一下LDAP是什么? - 它代表轻量级目录访问协议.它是一种开放的,与供应商无关的协议,用于 ...

  5. Java删除List指定元素

    List<String> lists = new ArrayList<>(); list.add("123"); list.add("456&qu ...

  6. JavaScript 30 - 3 学习笔记

    今天学习的是JavaScript 30-3 ---css Variables 实现的效果如下图所示. 废话不多,我们直接来看代码. html: <h1>大家好,这个一个<span c ...

  7. thinkphp分页集成

    控制器: $User = M('webcase'); //  实例化 User 对象 $list = $User->order('id desc')->page($_GET['p'].', ...

  8. Json字符串转excel表格文件

    假如我们有一段json串,该json串是由一系列结构相同的数据集合组成,如下: { "data": [ { "groupId": "com.test. ...

  9. http协议参数详解

    整理一下http协议中的一些参数详解 截取了一个当前项目中的请求作为示例: Genaral:通用头 Request URL:当前请求的请求地址 Request Method:请求类型 get.post ...

  10. WPF中播放视频音频

    首先要在WPF中播放视频和音频,我们就需要用到MediaElement控件,下面我们示例播放音频和视频. 用MediaElement播放音频: 第一步:将你需要播放的音频(mp3)放在你WPF项目的D ...