python-迭代器

python-迭代器,第1张

概述字符串、列表、元组、字典、集合都可以被for循环,而int和bool不能被for循环,说明他们是不可迭代的。 怎么样才能给证明,我们知道的数据类型是可迭代的.使用模块collections中的Iterable和isinstance进行类型的判断。 from collections import Iterabledic = {"a": "b", "c": "d"}lis = ["a", "b"

字符串、列表、元组、字典、集合都可以被for循环,而int和bool不能被for循环,说明他们是不可迭代的。
怎么样才能给证明,我们知道的数据类型是可迭代的.使用模块collections中的Iterable和isinstance进行类型的判断。

from collections import Iterabledic = {"a": "b","c": "d"}lis = ["a","b","c"]num = 123tu = (1,2,3)se = {1,3}bo = bool("a")str_ = "ABC"print(isinstance(dic,Iterable))  # Trueprint(isinstance(lis,Iterable))  # Trueprint(isinstance(num,Iterable))  # Falseprint(isinstance(tu,Iterable))   # Trueprint(isinstance(se,Iterable))   # Trueprint(isinstance(bo,Iterable))    # Falseprint(isinstance(str_,Iterable))  # True

上述就验证了bool和int不是可迭代的对象,其余的数据类型是可迭代的。

可迭代协议

??可以被迭代要满足的要求就叫做可迭代协议,可迭代协议:就是内部实现了__iter__方法。

print(set(dir(str)) & set(dir(dict)) &       set(dir(List)) & set(dir(tuple)) & set(dir(set)))  # 求交集

数据类型如果想要是可跌代的,在内部必须含有__iter__方法

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>
迭代器协议

??迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。

相对于迭代器列表和列表中多了什么样的方法。

dir_iter_List = dir([1,2].__iter__())  # 列表迭代器的方法dir_List = dir([1,2])  # 列表的方法# 进行差集运算print(set(dir_iter_List)-set(dir_List))  # {'__setstate__','__length_hint__','__next__'}

上述的运算结果可以看出,列表迭代器的方法比列表的方法多了{‘__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__())  # aprint(lis.__next__())  # bprint(lis.__next__())  # c

在进行__next__进行取值的时候,如果将所有的都去完之后,在取值,则将会报错!!!

lis = ["a","c"]  # 列表lis_iter = lis.__iter__()  # 列表迭代器print(lis_iter.__next__())  # aprint(lis_iter.__next__())  # bprint(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 Iterableprint(isinstance(range,Iterable))  # Falseprint("__next__" in dir(range))  # Falseprint("__iter__" in dir(range))  # True

上述的代码说明了,range是一个可迭代的对象,但是不是应该迭代器。

生成器

迭代器的:一种的调用方法直接返回,一种是可迭代对象通过执行iter方法得到,迭代器的好处就是可以节省内存。
在很多是时候,由于硬件资源的缺少,在写相关的程序的时候,往往考虑到内存的问题,怎么样才能在代码上进行实现?
这个就是叫一个生成器的东西。

在python中提供的生成器:

常规的函数中,使用yIEld来代替return语句返回的结果,在yIEld语句中,yIEld只能放回一个结果,在每个结果的中间,挂起函数的状态,也便下次函数从原先的位置进行执行。 生成器表达式:类似于列表的推导式,会产生一个对象,而不是产生一个结果列表,在生成器表式中,是也()进行创建的。
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__())结果:'''111aaa111aaa111aaa111aaa'''# 为什么是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 9g = func()print(g.__next__())   #1 2  g.send(None)print(g.send('123'))  # send = next+传值print(g.send('234'))  # send = next+传值# # 第一次调用生成器的时候使用send里边的值必须是None''''12123342349'''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))'''start118220abc'''

send是将括号中的内容传给了上一yIEld,然后yIEld接收的值就可以赋值给变量

send和__next__()区别:

send 和 next()都是让生成器向下走一次

send可以给上一个yIEld的位置传递值,在第一次执行生成器的时候不能直接使用send(),但是可以使用send(None)

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=" ")'''start1 None2 Noneabc end'''
总结

以上是内存溢出为你收集整理的python-迭代器全部内容,希望文章能够帮你解决python-迭代器所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1195422.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存