迭代器及生成器
迭代器
内部含有_iter_方法的数据类型,就是可迭代的,
如:
print('_iter_' in dir('abc'))的执行结果如下:(请看是否有_iter_)
['__add__', '__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
#迭代器比可迭代的多一个_next_方法
#迭代器:包含_next_,_iter_方法的就是迭代器
#包含_next_方法的可迭代对象就是迭代器
l = [1,2,3,4,5] lst_iter = l.__iter__() print(dir(l)) print('__iter__' in dir(lst_iter)) print('__next__' in dir(lst_iter)) print(set(dir(lst_iter)) - set(dir(l))) lst_iter.__next__() 执行结果如下: ['__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'] True True {'__length_hint__', '__next__', '__setstate__'}
# 例题: # l = ['ha','hei','he'] # lst_iter = l.__iter__() # print(lst_iter.__next__()) # print(lst_iter.__next__()) # print(lst_iter.__next__())
可迭代的 必须含有_iter_方法 #可迭代协议
迭代器比可迭代的多了一个_next_方法
迭代器:包含_next_,_iter_方法 #迭代器协议
包含_next_方法的可迭代对象就是迭代器
迭代器是可迭代的一部分
获得迭代器:可迭代的调用_iter_()
使用迭代器:迭代器_next_()
如何判断一个变量是不是迭代器或者可迭代的
方法一: print('_iter_' in dir([1,2,3,4])) print('_next_' in dir([1,2,3,4])) 方法二: from collections import Iterable from collections import Iterator print(isinstance([1,2,3,4,5],Iterable)) str_iter = 'abc'.__iter__() print(isinstance(str_iter,Iterator)) print(isinstance('abc',Iterator))
迭代器的特点:
惰性运算(要的时候才给,不要不给)
从前到后一次去取值,过程不可逆,不可重复
节省内存
用while循环模拟for循环的方法: l = [1,2,3,4,5] l_iter = l.__iter__() while True: try: print(l_iter.__next__()) except StopIteration: break
for 循环是让我们更简单的使用迭代器
用迭代器去值就不需要关心索引或者key的问题了
目前我们已知的可迭代的都是python提供给我们的(range(),f这里指的是文
件,enumerate()指的是枚举)
一个对象要想被for循环,这个对象如果有个__iter__方法,必须得返回一个迭代器.
# class Foo(object): # pass # # obj=Foo() # for item in obj: # print(item) # 要想被for循环,内部必须有iter方法 class Foo(object): def __iter__(self): return iter([1,2,3,4,5]) #列表是可迭代对象,iter(可迭代对象)就变成了迭代器 obj=Foo() for item in obj: print(item)
生成器
自己想写个可迭代的,---生成器
生成器的本质就是迭代器
因此生成器的所有好处都和迭代器一样
但是生成器是我们自己写的python代码
生成器的实现由两种方式:1.生成器函数,2.生成器表达式
def g_func(): yield 1 g = g_func() print(g) # generator 生成器 本质还是迭代器 print(g.__next__())
生成器函数和普通函数之间的区别
生成器函数中含有yield关键字
生成器函数调用的时候不会立即执行,而是返回一个生成器
def g_func(): for i in range(2000): yield i g = g_func() print(g.__next__()) print(g.__next__()) print(g.__next__())
例题
def cloth(): for i in range(1000): yield '衣服%s'%i g = cloth() for i in range(50): print(g.__next__())