python-迭代器
字符串、列表、元组、字典、集合都可以被for循环,而int和bool不能被for循环,说明他们是不可迭代的。 from collections import Iterable dic = {"a": "b","c": "d"} lis = ["a","b","c"] num = 123 tu = (1,2,3) se = {1,3} bo = bool("a") str_ = "ABC" print(isinstance(dic,Iterable)) # True print(isinstance(lis,Iterable)) # True print(isinstance(num,Iterable)) # False print(isinstance(tu,Iterable)) # True print(isinstance(se,Iterable)) # True print(isinstance(bo,Iterable)) # False print(isinstance(str_,Iterable)) # True 上述就验证了bool和int不是可迭代的对象,其余的数据类型是可迭代的。 可迭代协议??可以被迭代要满足的要求就叫做可迭代协议,可迭代协议:就是内部实现了 print(set(dir(str)) & set(dir(dict)) & set(dir(list)) & set(dir(tuple)) & set(dir(set))) # 求交集 数据类型如果想要是可跌代的,在内部必须含有 dic = {"a": "b","c"] tu = (1,3) print(dic.__iter__()) # <dict_keyiterator object at 0x000001F86CEA0598> print(lis.__iter__()) # <list_iterator object at 0x000001F86CEBCC50> print(tu.__iter__()) # <tuple_iterator object at 0x000001F86CEBCCC0> 迭代器协议??迭代器遵循迭代器协议:必须拥有 相对于迭代器列表和列表中多了什么样的方法。 dir_iter_list = dir([1,2].__iter__()) # 列表迭代器的方法 dir_list = dir([1,2]) # 列表的方法 # 进行差集运算 print(set(dir_iter_list)-set(dir_list)) # {'__setstate__','__length_hint__','__next__'} 上述的运算结果可以看出,列表迭代器的方法比列表的方法多了 dir_iter_list_length = [1,2].__iter__().__length_hint__() print(dir_iter_list_length) # 2 获取迭代器中元素的长度 # 根据索引值指定从哪里开始迭代 print([1,3,4,5,6].__iter__().__setstate__(3))???? # 元素一个一个的取 print(lis.__next__()) # a print(lis.__next__()) # b print(lis.__next__()) # c 在进行 lis = ["a","c"] # 列表 lis_iter = lis.__iter__() # 列表迭代器 print(lis_iter.__next__()) # a print(lis_iter.__next__()) # b print(lis_iter.__next__()) # c 元素已经是最后一个 print(lis_iter.__next__()) # StopIteration 在这种情况下,可以采取异常处理的机制进行处理。 lis = ["a","c"] # 列表 lis_iter = lis.__iter__() # 列表迭代器 while 1: try: # 异常处理 print(lis_iter.__next__()) except StopIteration as e: print("end!!!") break range()是迭代器吗?还是一个迭代的对象 from collections import Iterable print(isinstance(range,Iterable)) # False print("__next__" in dir(range)) # False print("__iter__" in dir(range)) # True 上述的代码说明了,range是一个可迭代的对象,但是不是应该迭代器。 生成器迭代器的:一种的调用方法直接返回,一种是可迭代对象通过执行iter方法得到,迭代器的好处就是可以节省内存。 在python中提供的生成器:
M = [[1,3],[4,6],[7,8,9]] data = (i[-1] for i in M ) print(data) # <generator object <genexpr> at 0x000001B892E615C8> 生成器函数??一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束 def generator(): print(111) yield "aaa" # yield 生成器的关键字 print(222) yield "222" g = generator() print(g) # 是一个生成器 <generator object generator at 0x00000193C07615C8> print(g.__next__()) print(g.__next__()) 上述的代码和下面的带会产生什么样的结果? def generator(): print(111) yield "aaa" # yield 生成器的关键字 print(222) yield "222" print(generator().__next__()) print(generator().__next__()) print(generator().__next__()) print(generator().__next__()) 结果: ''' 111 aaa 111 aaa 111 aaa 111 aaa ''' # 为什么是111 aaa 为什么没有222 "222" 产生这个的原因的generator().__netxt__()是一个生成器去实现了__next__方法,下面的generator().__next__()也相当于是另外一个生成器对象,只能打印111和返回"aaa",下面的222 "222"永远不实现。而上述的代码就可以实现,因为调用的同一个生成器,代码就会向下指向,执行到下一个yield 生成器的本质就是的一个迭代器 __next__()和send()send()和__next__()一样可以执行下一个yield def func(): print(1) a = yield 2 # 1.挂起 2.返回值 3.接受值 print(a) # '123' print(3) b = yield 4 print(b) #'234' c = yield 9 g = func() print(g.__next__()) #1 2 g.send(None) print(g.send('123')) # send = next+传值 print(g.send('234')) # send = next+传值 # # 第一次调用生成器的时候使用send里边的值必须是None '''' 1 2 123 3 4 234 9 ''' def func(): print("start") a = yield 1 print(a) b = yield 2 print(b) yield "abc" print("end") f = func() print(f.send(None)) print(f.send(18))# print(f.send(20)) ''' start 1 18 2 20 abc ''' send是将括号中的内容传给了上一yield,然后yield接收的值就可以赋值给变量 send和__next__()区别:
for获取内部的元素def func(): print("start") a = yield 1 print(a) b = yield 2 print(b) yield "abc" print("end") f = func() for i in f: print(i,end=" ") ''' start 1 None 2 None abc end ''' (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |