for item in Iterable本质
在理解迭代器之前,先知道for item in Iterable的执行过程,注意,并不是说for迭代后面必须要一个可迭代对象
只要要迭代的对象能够调用iter()方法,正确返回迭代器即可
- 先通过iter()函数获取可迭代对象Iterable的 迭代器
2 . 通过获取到的迭代器不断调用该迭代器next()方法来获取下一个值并将其赋值给item
3 . 当遇到StopIteration的异常后循环结束
这里提及到Iterable需要有两个方法可以调用 iter()和next() 方法,这两个方法对应对象的两个魔法函数
__iter__
以及__next__
, __iter__
要返回一个迭代器,__next__
需要返回数据。下面来讲解这两个方法以及迭代器,可迭代对象的关系。
可迭代对象(Iterable)
Python中任意的对象,只要它定义了可以返回一个迭代器的__iter__
方法。
>>>from collections import Iterator,Iterable
>>> class MyList(object):
... def __init__(self):
... self.container = []
... def add(self, item):
... self.container.append(item)
... def __iter__(self):
... """返回一个迭代器"""
... # 我们暂时忽略如何构造一个迭代器对象
... pass
...
>>> mylist = MyList()
>>> from collections import Iterable
>>> isinstance(mylist, Iterable)
True
>>>
# 这回测试发现添加了__iter__方法的mylist对象已经是一个可迭代对象了
isinstance(mylist, Iterable)可以判断是否是迭代器。
但是MyList对象还不能正常的工作,它虽然是一个可迭代对象但是并不能给for遍历,因为__iter__
方法没有返回一个迭代器,需要__iter__
返回一个迭代器。下面说一说迭代器如何实现。
迭代器(Iterator)
一个实现了__iter__
方法和__next__
方法的对象,就是迭代器。注:有些资料只说__next__
方法,但是在pyhton3调用instance(Iterator)会返回False。
迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据,实际上,在使用next()函数的时候,调用的就是迭代器对象的__next__
函数
所以,我们要想构造一个迭代器,就要实现它的__next__
函数, 但是这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现iter方法,而iter方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的iter方法返回自身即可。
实现一个简单的迭代器:
class MyIterator(object):
"""自定义的迭代器"""
def __init__(self, mylist):
self.mylist = mylist
# current用来记录当前访问到的位置
self.current = 0
def __next__(self):
if self.current < len(self.mylist.items):
item = self.mylist.items[self.current]
self.current += 1
return item
else:
raise StopIteration
def __iter__(self):
return self
用可迭代对象封装迭代器:
class MyList(object):
"""自定义的一个可迭代对象"""
def __init__(self):
self.items = []
def add(self, val):
self.items.append(val)
def __iter__(self):
myiterator = MyIterator(self)
return myiterator
Iterator和Iterable两者关系
- python3中可迭代对象(Iterable)是实现了iter方法就可以,迭代器(Iterator)是实现了iter方法和next方法的对象才可以,也就是说迭代器一定是可迭代对象,反过来不可。
- 一个对象可以同时既是可迭代对象又是迭代器,只要方法里有next(python3) 又有iter方法,惯用的做法是iter方法返回自己作为迭代器。
- 要给for遍历 需要对象实现iter方法并且正确返回一个迭代器。
- 如果一个对象定义了可以支持下标索引的
__getitem__
方法也是可以被for…in…循环的,但是isinstance(Iterable)却是错误的 - for…in…后面不一定是可迭代对象,
__getitem__
也可以
关于getitem和for迭代
是在类中定义了这个getitem 方法,那么它的实例对象(假定为p),可以像这样
p[key] 取值,当实例对象做p[key] 运算时,会调用类中的方法getitem。
一般如果想使用索引访问元素时,就可以在类中定义这个方法(getitem(self, key) )。
下面是一个例子:
class Mygetitem:
def __init__(self, text):
self.text = text
def __getitem__(self, index):
result = self.text[index].upper()
return result
p = Mygetitem('Python')
for c in p:
print(c)
当__getitem__
遇到异常时候终止for循环
isinstance(p, Iterable) = False
并不是可迭代对象,有些资料说可以被for迭代的就是可迭代对象我认为是不正确的。
Mygetitem是可以用iter(p)返回一个迭代器的。所以for迭代的本质是调用iter(Obj)得到一个迭代器,再调用里面的next()方法来。
网友评论