python进行曲——迭代生成

迭代器 - 概念

可迭代协议 : 内部含有__iter__方法的值/变量都是可迭代的
通过可迭代变成迭代器 : 可迭代变量.__iter__()返回一个迭代器
迭代器协议 : 内部含有__iter__方法和__next__方法的值/变量都是迭代器
迭代器的特点 :节省内存,惰性运算,一次性取值,只能按顺序取
可迭代和迭代器的关系:
所有的迭代器都是可迭代的,反之不成立
迭代器是特殊的存在
for循环和迭代器的关系:
无论是可迭代的还是迭代器都可以被for循环
如果直接循环迭代器,那么循环一次就没有了
如果循环的非迭代器,那么每一次循环都相当于从头到尾的循环
是因为在for循环中的所有非迭代器都会通过iter生成一个新的迭代器


迭代器引用
可迭代的/可迭代对象
for i in 7:print(i)
iterable 可迭代
整数类型 是不可迭代的
iter 迭代
iterable 可迭代的

dir函数查看一个数据类型内部含有哪些方法
两边带着双下划线的方法叫做"魔术方法","双下方法","内置方法"
这些方法都有一个特点:你可以调但是不需要你直接调用
ret_lst = dir([]) # 内置函数
print(ret_lst)
ret_str = dir('') # 内置函数
print(ret_str)
ret_num = dir(123) # 整数的内部是不含有__iter__方法的
print(ret_num)

可迭代协议 -- 只要是含有'__iter__'方法的数据类型都是可迭代的
是python规定的 : 可迭代类型 和 python语言之间的协议

检测某个变量/值 是不是可迭代的呢?
print('__iter__' in dir([]))
print('__iter__' in dir(123))

第二种检测方式
from collections import Iterable
print(isinstance([],Iterable)) # 内置函数,判断一个具体的值是不是某个数据类型的
print(isinstance(123,Iterable)) # 内置函数,判断一个具体的值是不是某个数据类型的

可以迭代的都可以使用for循环

print('__inter__' in dir([]))
print('__inter__' in dir(123))
from collections import Iterable
print(isinstance([],Iterable))
print(isinstance(123,Iterable))
什么是迭代器?
l = [1,2,3,4]
res = l.__iter__()
print(res)
list_iterator iterator迭代器
dir(l)
print(dir(res))
res中 但是不在l中的所有方法
print(set(dir(res))-set(dir(l)))
{'__next__', '__setstate__', '__length_hint__'}
迭代器中特有的方法,l中没有
print(res.__length_hint__()) # 迭代器中有多少个元素
for i in res:
print(i)
res.__setstate__(2) # 控制迭代器从哪儿开始迭代
for i in res:
print(i)
print(res.__next__()) # 从迭代器中取下一个值
print(res.__next__())
print(res.__next__())
print(res.__next__())
print(res.__next__())

for循环一个列表的时候必须用的
__next__取下一个值

迭代器协议 : 含有__next__和__iter__方法的变量/值都是迭代器

迭代器的特点:
具有next和iter方法
通过一个next多次执行就可以获得所有这个容器中的值
迭代器中的值只能取一次
不取的时候值不出现

for循环取值
for循环内部的机制就是迭代器取值的机制
在for循环执行的过程中 : 先把可迭代的变成一个迭代器,然后再从中一个一个的取值

range生成的就是一个迭代器,创建这个迭代器并不会真的把迭代器中的所有数据一次性生成
什么时候生成呢? 只有通过next取值的时候才会生成
记住你要多少个值 ,当前该给你什么,并且记住我下一个该给你什么,下一个和当前这个数的关系

f文件句柄
f记住 当前读到哪个位置了

a = list(range(1000000000))
print(a)

迭代器的作用就是节省内存,for循环就是利用了迭代器节省内存的特点来对python当中的变量来进行操作的


l = [1,2,3,4]
res1 = l.__iter__()
res2 = l.__iter__()
res1和res2都是迭代器
是两个完全不同的迭代器

for i in res1:
print(i)
print('------')
for i in res1:
print(i)
print('^^^^^^')
for i in l.__iter__():
print(i)
print('******')
for i in l.__iter__():
print(i)

for i in l:
print(i)
for i in l:
print(i)

自己创建一个迭代器
循环这个迭代器
dic = {'k':'v','k2':'v2'}
dic_iter = dic.__iter__()
print(dic_iter)

print(dic_iter.__next__())
for k in dic_iter:
print(k)

自己创建多个迭代器 : 每次执行iter方法就创建一个迭代器,每个迭代器都只能取值一次
循环这些迭代器
iter1 = dic.__iter__()
iter2 = dic.__iter__()

用while循环实现一个for循环的功能(循环list/dict)
l = [1,2,3,5,6,7,12,23,412]
l_iter = l.__iter__()
while True:
try: # 要保护的代码
print(l_iter.__next__())
except StopIteration: # 要保护的代码中一旦出现了StopIteration错误,程序不报错,直接执行break
print('报错啦')

count = 0
l_iter = l.__iter__()
while count < len(l):
print(l_iter.__next__())
count += 1

本质上for循环替我们做了上面程序的一系列操作:
生成迭代器
循环每一次对这个迭代器执行next
并且到迭代器的最后就停止

判断一个变量/值是否是迭代器的方法
lst_iterator = [].__iter__()
print('__iter__' in dir(lst_iterator))
print('__next__' in dir(lst_iterator))
print('__iter__' in dir(lst_iterator) and '__next__' in dir(lst_iterator))

f是一个迭代器还是一个可迭代的
range是一个迭代器还是一个可迭代的
f = open('file')
print('__iter__' in dir(f) and '__next__' in dir(f))

a = range(10)
print('__iter__' in dir(a))
print('__iter__' in dir(a) and '__next__' in dir(a))

第二种方法
from collections import Iterator
f = open('file')
print(isinstance(f,Iterator))
print(isinstance(range(10),Iterator))

a = range(10)
for i in a:
print(i)
for i in a:
print(i)


生成器概念

python语言自带的
生成器 : 程序员通过简单的函数就可以实现的
def func():
print('hello')
yield 1

g = func() # 调用"生成器函数"
print(g) # g generator(生成器)
调用就不会执行这个函数,而是返回一个生成器
print(dir(g)) # g是一个迭代器
所有的生成器都是迭代器

a = g.__next__()
print(a)

def func():
print('hello')
yield 1
print('world')
yield 2

g = func()
a = g.__next__()
print(a)
b = g.__next__()
print(b)
yield关键字的特点: 可以记录当前函数中执行的位置,下一次继续执行
next和yield是一对搭档 : next开始函数的执行 yield停止函数的执行




 

原文地址:https://www.cnblogs.com/Godisgirl/p/9916637.html