一 迭代器
双下方法 : 很少直接调用的方法。一般情况下,是通过其他语法触发的
可迭代的 —— 可迭代协议 含有__iter__的方法('__iter__' in dir(数据))
可迭代的一定可以被for循环
迭代器协议: 含有__iter__和__next__方法
迭代器一定可迭代,可迭代的通过调用iter()方法就能得到一个迭代器
迭代器的好处:
# 从容器类型中一个一个的取值,且只能取所有的数据取一次
# 节省内存空间
--迭代器并不会在内存中再占用一大块内存,
而是随着循环 每次生成一个
每次next每次给我一个
迭代器的用法
#iterator = l.__iter__() #iterator.__next__()
# for i in l:
# pass
直接给内存地址 print([].__iter__()) # <list_iterator object at 0x003A5D70> print(range(10)) # range(0, 10)
for
#只有 是可迭代对象的时候 才能用for
# for循环其实就是在使用迭代器
#当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代
#判断是否可迭代
print('__iter__' in dir(int)) False print('__iter__' in dir(bool)) False print('__iter__' in dir(str)) True print('__iter__' in dir(list)) print('__iter__' in dir(dict)) print('__iter__' in dir(set)) print('__iter__' in dir(tuple)) print('__iter__' in dir(enumerate([]))) print('__iter__' in dir(range(1))) #只有前两个False
dir([])
print(dir([])) #列表拥有的所有方法
print(dir([].__iter__())) print(set(dir([].__iter__())) - set(dir([]))) #{'__next__', '__setstate__', '__length_hint__'}
print(['a','bbb'].__iter__().__length_hint__()) #元素个数
二 生成器 —— 迭代器
生成器的本质就是迭代器
生成器的表现形式
生成器函数
生成器表达式
生成器函数:
含有yield关键字的函数就是生成器函数
特点:
调用函数的之后函数不执行,返回一个生成器
每次调用next方法的时候会取到一个值
直到取完最后一个,在执行next会报错
def generator(): print(1) yield 'a'
#生成器函数 : 执行之后会得到一个生成器作为返回值
ret = generator()
print(ret) # <generator object generator at 0x0058DB40>
print(ret.__next__()) # 1 a
def wahaha(): for i in range(2000000): yield '娃哈哈%s'%i g = wahaha() g1 = wahaha() print(g.__next__()) # 娃哈哈0 print(g1.__next__()) # 娃哈哈1 print(g1.__next__()) # 娃哈哈0 print(g1.__next__()) # 娃哈哈1 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
从生成器中取值的几个方法
# next
# for
# 数据类型的强制转换 : 占用内存
g = generator() #调用生成器函数得到一个生成器 print(list(g))
send 获取下一个值的效果和next基本一致
只是在获取下一个值的时候,给上一yield的位置传递一个数据
使用send的注意事项
第一次使用生成器的时候 必须用next获取第一个值
最后一个yield接受外部不到的值
def averager(): average = None sum = 0 count = 0 while True: num = yield average count+=1 sum += num average = sum/count f = averager() f.__next__() print(f.send(10)) print(f.send(20)) print(f.send(30))
预激生成器的装饰器 def init(func): #装饰器 def inner(*args,**kwargs): g = func(*args,**kwargs) #g = average() g.__next__() return g return inner @init def average(): sum = 0 count = 0 avg = 0 while True: num = yield avg sum += num # 10 count += 1 # 1 avg = sum/count avg_g = average() #===> inner ret = avg_g.send(10) print(ret) ret = avg_g.send(20) print(ret)
python3 ------- (yield from 容器型元素)的用法
def generator(): a = 'abcde' b = '12345' for i in a: yield i for i in b: yield i # def generator(): # a = 'abcde' # b = '12345' # yield from a # yield from b # g = generator() for i in g: print(i)
三 生成器推导式
#生成器函数 def init(func): #在调用被装饰生成器函数的时候首先用next激活生成器 def inner(*args,**kwargs): g = func(*args,**kwargs) next(g) return g return inner @init def averager(): total = 0.0 count = 0 average = None while True: term = yield average total += term count += 1 average = total/count g_avg = averager() # next(g_avg) 在装饰器中执行了next方法 print(g_avg.send(10)) print(g_avg.send(30)) print(g_avg.send(5)) #生成器表达式 laomuji=('鸡蛋%s' %i for i in range(10))#生成器表达式 print(laomuji) print(next(laomuji)) #next本质就是调用__next__ print(laomuji.__next__()) print(next(laomuji))