学习python有一段时间了,在学习过程中遇到很多难理解的东西,做一下总结,希望能对其他朋友有一些帮助。
完全是个人理解,难免有错,欢迎其他大神朋友们批评指正。
1 迭代
什么是迭代呢??我们可以这样理解,一个容器类型的数据,比如 列表[ ] 、元组 () 和 字典 { }, 我们可以把这样类型的数据放入for temp in [1,2,3] 当中,temp 被一次一次的赋值成为后面容器内数据,然后我们拿到temp进行一些想做的事情。那么for 循环中自动的帮我们把数据一次一次的取出来,可以理解成,这样的操作就是迭代。
2 可迭代对象
在python当中有有那么一些特定的数据类型,可以放入for in 循环当中,这样的数据类型,我们可以说他们是可迭代对象。
我们可以用 isinstance方法来检测一个对象是不是可迭代对象。
可迭代对象可以放入for in中迭代,也可以放入list() tuple()等帮我们快速生成一个数据。
上代码!
1 from collections import Iterable
2
3 print( isinstance( [] , Iterable ) ) #True
4 print( isinstance( {} , Iterable ) ) #True
5 print( isinstance( () , Iterable ) ) #True
6 print( isinstance( 1 , Iterable ) ) #False
从中我们可以看出来,列表、元组、字典都是可迭代对象。而整型数据不是可迭代对象。
可迭代对象的实质是怎么回事呢???? (一脸懵逼)
其实,可迭代对象的内部必须实现一个方法,__iter__()方法,这个方法的功能是,返回一个迭代器,这个迭代器是帮助自己进行迭代的。实现这个方法的对象,python就认为它是可迭代对象。
迭代器又是啥???(二脸懵逼)不要着急 稍后我再分享
上代码!!先看一看可迭代对象:
1 from collections import Iterable
2 #我们自己创建一个类 里面实现iter方法 python就认为它的对象是可迭代对象了
3 class MyIterableObj(object):
4 def __iter__(self):
5 pass
6
7 demo1 = MyIterableObj()
8 print(isinstance( demo1 , Iterable )) #True
从中可以看出来,我们自己写一个类,里面实现了iter方法,即使什么都没有做,创建一个对象之后,判断一下 python就认为这个对象是一个可迭代对象了。
3 迭代器
刚刚我们说了,可迭代对象里面的iter方法返回一个帮助自己迭代的迭代器。迭代器是什么呢??
其实我也不知道!(嘻嘻 笑哭) 开玩笑的啦~~~
在我的理解当中呢,迭代器是帮助可迭代对象一个一个把里面元素取出来的一个对象。迭代器类型的对象都是可迭代对象,为什么呢,我们来看一看实质。
迭代器的实质:
迭代器内部必须实现两个方法: __iter__() 和 __next__()
__iter__() 功能是返回一个迭代器,帮助我们自己这种类型进行迭代,因为自己就是迭代器,所以迭代器中的__iter__() 返回的是self自己
__next__() 功能是: 简单的说就是返回当前元素的,就像列表当中,取出第一个元素,再调用next的时候就取出了第二个元素。 但是在for循环当中放入列表的时候,for是怎么知道列表最后一个元素都已经取完了呢????(我的天啊!不知道啊!!呜呜!!!)别着急,继续往下看
复杂的说, next会做两件事:1 如果当前数据没有超出范围,这次当前值返回,然后自己进行标记,找到下一个要返回的值。
2 如果当前迭代器上次取出了最后一个元素,这一次当前数据是在范围之外的,那么就抛出异常(StopIteration),告诉for循环等一些内建工具,迭代结束了。
不是很理解??没关系,上代码我们来看看!!
我们先看一看 python中认为什么样的东西是迭代器:
from collections import Iterator
print( isinstance( [] , Iterator ) ) #False 很显然,可迭代对象不是迭代器
print( isinstance( [].__iter__() , Iterator ) ) #True 这是调用了可迭代对象的iter方法得到一个迭代器对象
#在python中 内建了 iter() 方法和 next() 方法,把对象传进去与__iter__ 和 __next__ 相同功能
print( isinstance( iter([]) , Iterator ) ) #True
# 像我说的 我们自己实现一个迭代器
class MyIterator(object):
def __iter__(self):
pass
def __next__(self):
pass
demo2 = MyIterator()
print( isinstance(demo2 , Iterator ) ) # True
看的出来,我们自己的类对象里面只要具有这两个方法 python就认为他是迭代器了。
大家还记不记得我说过,迭代器都是可迭代对象, 因为迭代器一定有__iter__方法,所以它一定是迭代对象
ok!接下来呢,我们把两个函数的业务逻辑补全,看一看迭代器两个方法实际上在干什么??
我们来实现一个 传入一个n 给我们迭代出 0到n 的迭代器 这个功能就好像是 range(n) 一样 我们自己实现一下!
1 '''
2 接下来,我们具体实现一个能够完成功能, 能够放入for循环遍历的迭代器!! 啊好刺激啊!!
3 我们要实现的业务是: 传入一个参数n , 我们要迭代出 0到n的数
4 '''
5 class NumIterator(object):
6 #初始化我们接收一个参数n 告诉我们迭代到多少结束
7 def __init__(self , n):
8 self.n = n
9 #我们实际上是把 i 交给函数调用者
10 self.i = 0
11 # iter方法 返回一个迭代器,自己就是迭代器 所以返回自己
12 def __iter__(self):
13 return self
14 # next方法 判断是否越界 如果不越界返回一个元素 如果越界了抛出异常
15 def __next__(self):
16 #如果 没有越界, 我们返回给调用者迭代结果,并且自己记录下一次迭代的位置
17 if self.i <= self.n:
18 res = self.i
19 self.i += 1
20 return res
21 # 进入else说明i已经超过n 迭代越界了 抛出异常告诉for循环 迭代结束了
22 else:
23 #如果不抛出这个异常,for循环不知道什么时候停止迭代 会不停的调用next 陷入死循环
24 raise StopIteration
25
26 #一个前3的自然数的迭代器对象
27 demo3 = NumIterator(3)
28 # 之前说过, 我们可以调用python内建的next方法来获取迭代器的元素
29 print( next(demo3) ) # 0
30 print( next(demo3) ) # 1
31 print( next(demo3) ) # 2
32 print( next(demo3) ) # 3
33 #print( next(demo3) ) # 这时候再调用会抛出异常 因为越界了!
34
35 #同样我们自己写的迭代器能够放入for循环当中
36 demo4 = NumIterator(10)
37 for num in demo4 :
38 print(num)
39 #我们发现,会打印出从0 到 10 然后for循环就停了
看完上面的代码,我来解释一下 其实for循环的实质:
for 不知道我们放在in后面的是可迭代对象还是迭代器,他会先调用iter方法拿到一个迭代器,然后不停的调用next方法取到值,然后提供给我们,一直到取某个值的时候接收到了一个StopIteration异常,for循环就终止了。
ok!! 到这里呢,可迭代对象、迭代器的知识就跟大家分享完了。
不知道小伙伴们都有没有理解,希望对一些不理解这些深层次东西的同学有一些帮助!!
欢迎大家批评指正~~~~谢谢大家的参考!
我是稀里糊涂的林老冷~