day13 迭代器和生成器
1复习
# 函数 —— 2天 # 函数的定义和调用 # def 函数名(形参): #函数体 #return 返回值 #被调用的地方接收 #调用 函数名(实参) # 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),**kwargs # 站在实参的角度上 : 按照位置传,按照关键字传 # 返回值:没有返回值 返回一个值 返回多个值 # 接收返回值:没有返回值不接收,返回一个值用一个变量接收,返回多个值用一个变量或者对应数目的变量接收 # 闭包函数 —— 在内部函数引用外部函数的变量 # 装饰器函数—— 装饰器一定是闭包函数 # 装饰器的作用 : 在不改变原来函数的调用方式的情况下 在这个函数的前后添加新的功能 # 完美的符合了一个开发原则 :开放封闭原则 # 对扩展是开发的 # 对修改是封闭的 # 基础的装饰器 # from functools import wraps # def wrapper(func): # @wraps(func) # def inner(*args,**kwargs): # '''在函数被调用之前添加的代码''' # ret = func(*args,**kwargs) # func是被装饰的函数 在这里被调用 # '''在函数被调用之后添加的代码''' # return ret # return inner # 使用 —— @wrapper # @wrapper # def func(): #inner # pass # # func.__name__ # 带参数的装饰器 # @wrapper -- > @warapper(argument) # 三层嵌套函数 # def outer(形参): # def wrapper(func): # def inner(*args,**kwargs): # '''在函数被调用之前添加的代码''' # ret = func(*args,**kwargs) # func是被装饰的函数 在这里被调用 # '''在函数被调用之后添加的代码''' # return ret # return inner # return wrapper # @outer(True) # def func(): # pass # 多个装饰器装饰一个函数 # 俄罗斯套娃 #def wrapper1(func): # @wraps(func) # def inner(*args,**kwargs): # print('before 1') # print('******') # ret = func(*args,**kwargs) # func是被装饰的函数 在这里被调用 # '''在函数被调用之后添加的代码''' # return ret # def wrapper2(func): # @wraps(func) # def inner(*args,**kwargs): # print('before 2') # ret = func(*args,**kwargs) # func是被装饰的函数 在这里被调用 # '''在函数被调用之后添加的代码''' # return ret # @wrapper1 # @wrapper2 # def func(): # print('111') # 迭代器和生成器 —— 两天 # 内置函数 —— 两天
2迭代器
1双下方法
#双下方法 print([1].__add__([2])) print([1]+[2]) <<< [1, 2] [1, 2]
#list dic str set tuple range enumerate print(dir([])) #告诉我列表的所有方法 ret=set(dir([]))&set(dir({}))&set(dir(""))&set(dir(range(12))) print(ret) print(set(dir([]))-set(dir({}))) <<< ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] {'__gt__', '__reduce_ex__', '__doc__', '__getitem__', '__len__', '__sizeof__', '__new__', '__eq__', '__delattr__', '__str__', '__reduce__', '__format__', '__repr__', '__ne__', '__le__', '__lt__', '__iter__', '__getattribute__', '__init__', '__contains__', '__subclasshook__', '__setattr__', '__dir__', '__class__', '__ge__', '__init_subclass__', '__hash__'} {'__iadd__', '__imul__', '__mul__', 'count', 'index', 'sort', 'reverse', 'append', '__rmul__', 'extend', 'remove', 'insert', '__reversed__', '__add__'}
''' 可迭代协议: 只要能被for循环的数据类型 就一定有__iter__方法 [] iterable 只要含有__iter__方法的都是可迭代的 迭代器协议: 一个列表执行了__iter__()之后的返回值就是一个迭代器 [].__iter__ iteraor 内部含有__iter__和__next__方法的就是迭代器 通过__next__()就可以从迭代器中一个一个取值 :print(iterator.__next__()) for: for循环其实就是在使用迭代器 只有是可迭代对象的时候才能用for 当我们用一个新的变量 不确定能不能for循环的时候 就判断是否可迭代 判断方法 from _collections_abc import Iterable print(isinstance([],Iterable)) print('__iter__'in dir([])) '''
2协议
#协议 print([].__iter__()) #打印迭代器直接给你内存地址 print(set(dir([].__iter__()))-set(dir([]))) #列表迭代器相当于列表的独特方法 print([1,'a','bbb'].__iter__().__length_hint__()) #__length_hint__求元素个数 l=[1,2,3] iterator=l.__iter__() print(iterator.__next__()) print(iterator.__next__()) print(iterator.__next__()) <<< <list_iterator object at 0x0000026048DF4438> {'__setstate__', '__next__', '__length_hint__'} 3 1 2 3
3判断方法
#判断方法 print('__iter__'in dir([])) print('__iter__'in dir([].__iter__())) from _collections_abc import Iterable #弃用警告:不推荐使用或导入来自collections from collections.abc import Iterator #而不是“collections.abc”中的ABC print(isinstance([],Iterator)) # 并且在python3.8中它将停止工作 print(isinstance([],Iterable)) #判断[]是不是可迭代的 <<< True True False True
4for
#for #只要有iter方法就能被循环 for循环其实就是在使用迭代器 l=[1,2,3] for i in l.__iter__(): print(i) print([].__iter__()) #打印迭代器直接给你内存地址 print(range(10).__iter__()) print(range(10)) l=[1,2,3] for i in l: print(i) if i ==2: break <<< 1 2 3 <list_iterator object at 0x0000024B1E314208> <range_iterator object at 0x0000024B1DFAD830> range(0, 10) 1 2
5迭代器的好处
# 迭代器的好处 ''' 从容器类型中一个个取值 会把所有值都取到 节省内存空间 迭代器并不会在内存中占一大块内存 而是随着循环 每次生成一个next给我一个''' l=[1,2,3,4] iterator=l.__iter__() while 1: print(iterator.__next__()) <<< Traceback (most recent call last): File "C:/python全栈/me第一部分/day13 迭代器和生成器.py", line 76, in <module> print(iterator.__next__()) StopIteration 1 2 3 4
print(range(10000)) print(list(range(3))) def f(): for i in range(200): i="wahaha%s"%i return i print(f()) <<< range(0, 10000) [0, 1, 2] wahaha199
3.生成器
#3 生成器 #生成器函数 本质上就是我们自己写的函数 #只要含有yield关键字的函数都是生成器函数 #yield不能和return共用且需要写在函数内 def generetor(): print(1) yield 'a' ret=generetor() print(ret) print(ret.__next__()) <<< <generator object generetor at 0x00000246FE4C8A98> 1 a
1.生成器函数 执行之后会得到一个生成器作为一个返回值
#生成器函数 执行之后会得到一个生成器作为一个返回值 def generetor1(): print(1) yield 'a' print(2) yield 'b' yield 'c' g=generetor1() print(g) ret=g.__next__() print(ret) # for i in g: # print(i) 1 a 2 b c ret=g.__next__() print(ret) ret = g.__next__() print(ret) <<< 1 a 2 b c
2.next方法获取生成器的值
# 娃哈哈 import time def wahaha(): for i in range(200000): yield '娃哈哈%s'% i g=wahaha() g1=wahaha() print(g.__next__()) print(g.__next__()) print(g1.__next__()) g=wahaha() count=0 a=time.time() for i in g: count+=1 print(i) if count>3: break b=time.time() print(b-a) print("***",g.__next__()) for i in g: count+=1 print(i) if count>6: break print("&&",g.__next__()) <<< 娃哈哈0 娃哈哈1 娃哈哈0 娃哈哈0 娃哈哈1 娃哈哈2 娃哈哈3 0.0 *** 娃哈哈4 娃哈哈5 娃哈哈6 娃哈哈7 && 娃哈哈8
4 利用生成器监听文件输入
#4 利用生成器监听文件输入 def tail(filename): f=open(filename,encoding='utf-8') while True: line=f.readline() if line.strip(): yield line.strip() #使用生成器在后面的操作中更灵活想加*就加 g=tail('file') # print(g.__next__()) for i in g: if 'python' in i: print("***",i) <<< *** python

【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步