迭代器,生成器
一、迭代器
Iterable可迭代的------>__iter__
注:只要含有_iter_ 方法的都是可迭代的
[].__iter__ 迭代器------>__next__
注:通过next就可以从迭代器中一个一个获取值
总结:
只要含有__iter__ 方法都是可迭代的——>可迭代协议
内部含有__next__和__iter__ 方法的就是迭代器
print('__iter__' in dir( [].__iter__())) print('__next__' in dir( [].__iter__()))
迭代器协议和可迭代协议
1)、可以被for循环的都是可迭代的
2)、可迭代的内部都有__iter__ 方法
3)、只要是迭代器,一定可迭代
4)、可迭代的__iter__ 方法就可以得到一个迭代器
5)、迭代器中的__next__方法可以一个一个的获取值
for
只要是可迭代对象的时候,才能用for
当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代
isinstance() 判断列表是不是可迭代的或是迭代器
迭代器的好处:
从容器类型中一个一个的取值,会把所有的值都取到
节省内存空间
迭代器并不会在内存中再占用一大块内存,而是随着循环,每次生成一个,每次next每次给一个
def wahaha(): for i in range(2000000): yield '娃哈哈%s'%i g = wahaha() count = 0 for i in g: count +=1 print(i) if count > 50: break print('*******',g.__next__()) for i in g: count +=1 print(i) if count > 100: break
二、生成器
本质:迭代器
迭代器函数:执行之后会得到一个生成器作为返回值
1)、只要含有yeild关键字的函数都是生成器函数
2)、yelid不能和return公用且需要写在函数内
def generator(): print(1) yield 'a' print(2) yield 'b' yield 'c' g = generator() # for i in g: # print(i) ret = g.__next__() print(ret) ret = g.__next__() print(ret) ret = g.__next__() print(ret)
生成器的特点:
1)、调用函数之后函数不执行,返回一个生成器
2)、每次调用next方法的时候会取到一个值
3)、直到取完最后一个,再执行next会报错
从生成器中取值的几个方法:
1)、next
2)、for
3)、数据类型的强制转换:占用内存
三、生成器函数的进阶
send获取下一个值的效果和next基本一样,只是在获取下一个值的时候,给一个值的位置传递一个数据
使用send的注意事项
1)、send作用范围和next一样
2)、第一次使用生成器的时候,是用next回去下一个值
3)、最后一个yield不能接受外部的值
def generator(): print(123) yield 1 print(456) content=yield 2 print("===",content) print(789) yield g=generator() ret=g.__next__() print("***",ret) ret=g.__next__() print("***",ret) ret=g.send("hello") print("***",ret) ret=g.__next__() print("***",ret)
生成器的应用
预激生成器的装饰器
四、生成器的表达式
列表推导式格式:
[每一个元素或者是和元素相关的操作 for 元素 in 可迭代数据类型] #遍历之后挨个处理
[满足条件的元素相关的操作 for 元素 in 可迭代数据类型 if 元素相关的条件] #筛选功能
列表推导式和生成器表达式:
1)、括号不一样
2)、返回的值不一样——>几乎不占用内存空间(生成器表达式)
列表推导式:
例1、30以内所有能被3整除的数
ret = [i for i in range(30) if i%3 == 0] #完整的列表推导式 g = (i for i in range(30) if i%3 == 0) #完整的生成器推导式 print(ret)
例2、30以内所有能被3整除的数的平方
ret = [i*i for i in (1,2,3,4) if i%3 == 0] ret = (i*i for i in range(30) if i%3 == 0) print(ret)
例3、找到嵌套列表中名字含有两个‘e’的所有名字
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] ret=[name for li in names for name in li if name.count("e")==2] print(ret) #['Jefferson', 'Wesley', 'Steven', 'Jennifer']
字典推导式
例1、将一个字典的key和value对调
mcase = {'a': 10, 'b': 34} ret={mcase[k]:k for k in mcase} print(ret) #{10: 'a', 34: 'b'}
例2、合并大小写对应的value值,将k统一成小写
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3} ret={k.lower():mcase.get(k.lower(),0)+mcase.get(k.upper(),0)for k in mcase} print(ret) #{'b': 34, 'a': 17, 'z': 3}
集合推导式,自带去重效果
squared={i**2 for i in [-1,1,3]} print(squared) #{1, 9}