一、迭代器
# 双下方法:带双下划线叫双下方法 print([1].__add__([2])) print([1]+[2]) [1, 2] [1, 2]
dir():用来展示xx拥有的所有使用方法
只要是能被for循环的数据类型,就一定拥有__iter__方法:
# 判断是否可迭代 print("__iter__" in dir(int)) # False print("__iter__" in dir(bool)) # False print("__iter__" in dir(list)) # True print("__iter__" in dir(dict)) # True print("__iter__" in dir(set)) # True print("__iter__" in dir(tuple)) # True print("__iter__" in dir(enumerate([]))) # True print("__iter__" in dir(range(2))) # True
一个列表执行了__iter__()之后的返回值就是一个迭代器:
print([].__iter__()) # <list_iterator object at 0x000000000109B390>
示例:
lis = [1, 2] l = lis.__iter__() # 把列表转换成迭代器 print(l.__next__()) # 通过__next__方法就可以从迭代器中一个一个地取值 print(l.__next__()) print(l.__next__()) # 报错
可迭代:只要含有__iter__方法都是可迭代的
迭代器:同时含有__next__和__iter__方法就是迭代器
判断xx是否可迭代 或 是否是迭代器:
from collections import Iterable from collections import Iterator print(isinstance([], Iterable)) # True 可迭代 print(isinstance([], Iterator)) # False 不是迭代器
总结:
- 得到一个迭代器格式:可迭代.__iter__()
- 迭代器中的__next__()方法可以一个一个的获取值
- 只有是可迭代对象的时候,才能用for循环
- 当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代(内部是否有__iter__方法)
迭代器的好处:
- 从容器类型中一个一个的取值,可以把所有的值都取到
- 节省内存空间,迭代器并不会在内存中占用一大块内存,而是随着循环,每次取一点,当然也可以__next__()获取一个值
二、生成器(本质还是迭代器)
# 生成器函数 def func(): yield "123" ret = func() print(ret) # <generator object func at 0x00000000007C1EB8> print(ret.__next__()) # 123
注意:
- 只要含有yield关键字的函数都是生成器函数
- yield不能和return共用,且需要写在函数内
# yield把返回值返回来,每次__next__()取一个值,并且下一个__next__()会接着取下一个值 # next(xx)等价于xx.__next__() def func(): for i in range(1, 4): yield "傻逼{}号".format(i) ret = func() print(next(ret)) # 傻逼1号 print(next(ret)) # 傻逼2号 print(next(ret)) # 傻逼3号 print(next(ret)) # 报错,没得取了
生成器实现监听文件输入:
def monitor(filename): f = open(filename, encoding="utf-8") while True: for line in f: if line.strip(): yield line.strip() ret = monitor("1.txt") for i in ret: if "pd" in i: print(i)