1. 迭代器
(1)迭代器——iterator
[].__iter__(),通过__next__方法就可以从迭代器中一个一个取值
(2)可迭代的——iterable
只要含有__iter__方法的都是可迭代的
(3)相关协议
可迭代协议 —— 只要含有__iter__方法的都是可迭代的,可以被for循环的都是可迭代的
迭代器协议 —— 内部含有__next__和__iter__方法的就是迭代器
(4)是否是迭代器的判断
以下几种情况可能是迭代:
<1>.iterator——print([].__iter__()) #<list_iterator object at 0x00000277E7E0CE10>
<2>.可迭代对象——print(range(10))
<3>.直接给内存地址
只有 是可迭代对象的时候,才能有for循环——for循环其实就是在使用迭代器
遇到新变量,不确定能不能for循环的时候,可以判断其是否可迭代
(5)迭代器和可迭代的对比
迭代器一定可迭代,可迭代的不一定是迭代器
可迭代的.__iter__()方法就可以得到一个迭代器
迭代器中的__next__方法可以一个一个的获取值
(6)迭代器的好处
<1>从容器类型中一个一个的取值,会把所有值都取到
<2>节省内存空间
迭代器并不会在内存中占用一大块内存,而是随着循环每次生成一个,或者每次next每次生成一个
2. 生成器
(1)本质
生成器的本质就是迭代器
(2)生成器函数
含有关键字yield的函数就是生成器函数,关键字yield只能写在函数内部,不会结束函数,且不能与return共用
def generator(): print(1) yield 'a' print(2) yield 'b' # 生成器函数:执行之后会得到一个生成器作为函数的返回值 ret = generator() print(ret) print(ret.__next__()) print(ret.__next__())
运行结果:
特点:
调用函数的时候函数不执行,返回一个生成器
每次调用next方法的时候会取到一个值
直到取完最后一个,在执行就会报错
(3)各种推导式
表达式格式:
遍历操作:[每一个元素/和元素相关的操作 for 元素 in 可迭代数据类型]
筛选功能:[满足条件的元素相关的操作 for 元素 in 可迭代数据类型]
<1> 生成器表达式
老母鸡 = ('鸡蛋%s'%i for i in range(10)) #生成器表达式 print(老母鸡) for 蛋 in 老母鸡: print(蛋)
# 面试——取一个next,for循环执行一次 g = (i*i for i in range(10)) print(g.__next__()) # 1:取一个next,for循环执行一次 print(g.__next__()) # 4:取一个next,for循环执行一次 print(g.__next__()) # 9:取一个next,for循环执行一次 print(g.__next__()) # 16:取一个next,for循环执行一次
<2> 列表推导式
# 30以内所有能被3整除的数 ret = [i for i in range(30) if i%3 == 0] print(ret) #[0, 3, 6, 9, 12, 15, 18, 21, 24, 27] # 30以内所有能被3整除的数的平方 ret = [i*i for i in range(30) if i%3 == 0] print(ret) #[0, 9, 36, 81, 144, 225, 324, 441, 576, 729] #找嵌套列表中名字含有两个e的名字 names = [['tom','billy','jefference','aneedhg'], ['alice','jill','ehdjbse']] ret = [name for lst in names for name in lst if name.count('e') == 2] print(ret) #['aneedhg', 'ehdjbse']
<3> 字典推导式
# 将一个字典的key和value对调 mcase = {'a':10,'b':34} mcase_frequency = {mcase[k]:k for k in mcase} print(mcase_frequency) #{10: 'a', 34: 'b'} # 合并大小写对应的value的值,将k统一写成小写 mcase = {'a':10,'b':34,'A':7,'Z':3} mcase_frequency = {k.lower():mcase.get(k.lower(),0 )+mcase.get(k.upper(),0)for k in mcase} print(mcase_frequency) #{'a': 17, 'b': 34, 'z': 3}
<4> 集合推导式
# 计算列表中每个值的平方(集合推导式自带结果去重功能) squared = {x**2 for x in [1,-1,2]} print(squared) #{1, 4}
生成器表达式和其他各种表达式的区别:
括号不一样
返回值不一样(生成器表达式几乎不占用内存)
(4)生成器的优点
延迟计算,一次返回一个结果