python基础15下_迭代器_生成器
print(dir([])) #告诉我列表拥有的所有方法
# 双下方法
# print([1].__add__([2]))
print([1]+[2])
ret = set(dir([]))&set(dir({}))&set(dir(''))&set(dir(range(10)))
print(ret) #iterable
print('***'.center(50,'-'))
# 只要是能被for循环的数据类型 就一定拥有__iter__方法
print('__iter__' in dir(int))
print('__iter__' in dir(bool))
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)))
# Iterable 可迭代的 -- > __iter__ # 只要含有__iter__方法的都是可迭代的
# [].__iter__() 迭代器 -- > __next__ # 通过next就可以从迭代器中一个一个的取值
# 只要含有__iter__方法的都是可迭代的 —— 可迭代协议
# 迭代器的概念
# 迭代器协议 —— 内部含有__next__和__iter__方法的就是迭代器
# 迭代器协议和可迭代协议
# 可以被for循环的都是可迭代的
# 可迭代的内部都有__iter__方法
# 只要是迭代器 一定可迭代
# 可迭代的.__iter__()方法就可以得到一个迭代器
# 迭代器中的__next__()方法可以一个一个的获取值
from collections import Iterable
from collections import Iterator
print('****'.center(50,'_'))
print(isinstance([],Iterator)) # False 不是迭代器
print(isinstance([],Iterable)) # True 是可迭代的
#迭代器的好处:
# 从容器类型中一个一个的取值,会把所有的值都取到。
# 节省内存空间
#迭代器并不会在内存中再占用一大块内存,
# 而是随着循环 每次生成一个
# 每次next每次给我一个
# 生成器 —— 迭代器
# 生成器函数 —— 本质上就是我们自己写得函数
# 生成器表达式
#只要含有yield关键字的函数都是生成器函数
# yield不能和return共用且需要写在函数内
def generator():
print(1)
yield 'a'
# #生成器函数 : 执行之后会得到一个生成器作为返回值
ret = generator() # 拿到生成器
print(ret) # 打印内存地址
print(ret.__next__()) # 执行函数体,直到遇到 yield
def generator2():
print(111)
yield 'aaa'
print(222)
yield 'bbb'
yield 'ccc'
g = generator2()
# for i in g:
# print(i)
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
#娃哈哈%i
def wahaha():
for i in range(2000000):
yield '娃哈哈%s'%i
g = wahaha()
g1 = wahaha() # 两个独立的生成器
print(g.__next__())
print(g.__next__())
print(g1.__next__())
print(g1.__next__())
gg = wahaha()
count = 0
for i in gg:
count +=1
print(i)
if count > 50:
break
print('*******',gg.__next__()) # 生成器继续前面的往下走
for i in gg: # 生成器继续前面的往下走
count +=1
print(i)
if count > 100:
break
生成器与send方法
# 从生成器中取值的几个方法
# next
# for
# 数据类型的强制转换 : 缺点:占用内存
def generator():
print(123)
content = yield 1
print('=======',content)
print(456)
arg = yield 2
''''''
yield
g1 = generator()
g2 = generator()
g1.__next__()
g2.__next__()
print('>>>>>',generator().__next__())
print('***',generator().__next__())
g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello') # send的效果和next一样, 但是多了传递数据的功能
print('***',ret)
# send 获取下一个值的效果和next基本一致
# 只是在获取下一个值的时候,给上一yield的位置传递一个数据
# 使用send的注意事项
# 第一次使用生成器的时候 是用next获取下一个值
# 最后一个yield不能接受外部的值
def generator():
print(123)
content = yield 1
print('=======', content)
print(456)
yield 2
''''''
yield
g = generator()
ret = g.__next__()
print('+++', ret)
res = g.send('hello') # send的效果和next一样
print('--->', res)
# send 获取下一个值的效果和next基本一致
# 只是在获取下一个值的时候,给上一yield的位置传递一个数据
# 使用send的注意事项
# 第一次使用生成器的时候 是用next获取下一个值
# 最后一个yield不能接受外部的值
# 案例应用: 获取移动平均值
# 10 20 30 10
# 10 15 20 17.5
# avg = sum/count
def avgs():
sum = 0
cnt = 0
avg = 0
while True:
num = yield avg
sum += num
cnt += 1
avg = sum / cnt
g = avgs()
g.__next__()
avg1 = g.send(10)
avg1 = g.send(8)
print(avg1)
avg2 = g.send(6)
print(avg2)
利用生成器来监视文件内容:
# 文件内容监视
def tail(filename):
with open(filename,encoding='utf8') as f:
while 1:
line = f.readline()
if line.strip():
# print(line)
yield line.strip()
g = tail('file')
for i in g:
if 'python' in i:
print('***',i)
给生成器函数加上装饰器,省掉一步 __next__()
# 预激生成器的装饰器
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)
直接 yield from
def gen():
a = 'abcdef'
b = '12345'
yield from a # 直接对容器类型生成器
yield from b
g = gen()
# for i in g:
# print(i)
print(g.__next__())
print(g.__next__())
print(g.__next__())
print(g.__next__())
两个生成器的小例子:
# 3.处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕
def check_file(filename, txt):
with open(filename, encoding='utf8') as f:
for i in f:
if txt in i:
yield i
g = check_file('a.txt', '正当防卫')
for i in g:
print(i.strip())
# 4.写生成器,从文件中读取内容,在每一次读取到的内容之前加上‘***’之后再返回给用户。
def read_file(filename):
with open(filename, encoding='utf-8') as f: # 句柄 : handler,文件操作符,文件句柄
for i in f:
yield '***' + i
for i in read_file('a.txt'):
print(i.strip())
生成器表达式遇到循环
def demo():
for i in range(4):
yield i
g = demo()
g1 =(i for i in g)
g2 =(i for i in g1)
# 以上所有都没干活
# print(list(g)) # 如果这里list了,则下面两个都取不到值,因为已经空了。
print(list(g1)) # list 取走了所有 g1 的值
print(list(g2)) # g2 已经空了,没有值
#### 生成器表达式 循环
def add(n,i):
return n+i
def test():
for i in range(4):
yield i
g=test()
for n in [1,10,5]:
g=(add(n,i) for i in g)
# 遇到上面的for循环生成器表达式,就把它拆开如下:
# n = 1
# g=(add(n,i) for i in test())
# n = 10
# g=(add(n,i) for i in (add(n,i) for i in test()))
# n = 5
# g=(add(n,i) for i in (add(n,i) for i in (add(n,i) for i in test())))
# 上面一句的结果 g=(15,16,17,18)
print(list(g)) # [15,16,17,18]

浙公网安备 33010602011771号