如何理解迭代对象迭代器以及迭代协议:
Iterable Iterator
1、可迭代对象和迭代器
可迭代的对象有个 __iter__ 方法,每次都实例化一个新的迭代器;而迭代器要实现 __next__ 方法,返回单个元素,此外还要实现 __iter__ 方法,返回迭代器本身
可迭代的对象一定不能是自身的迭代器。也就是说,可迭代的对象必须实现
__iter__ 方法,但不能实现 __next__ 方法
2、迭代器:
迭代器是这样的对象:实现了无参数的 __next__ 方法,返回序列中的下一个元素;如果没有元素了,那么抛出 StopIteration 异常。 Python 中的迭代器还实现了__iter__ 方法,因此迭代器可以迭代。
3、序列可以迭代原因
iter 函数:解释器需要迭代对象X时,会自动调用iter(X)
4、 内置iter函数作用
1、检查对象是否实现了__iter__方法,如果实现就调用,获取一个迭代器。
2、如果没有实现__iter__,但是有__getitem__方法,Python会创建一个迭代器,尝试按顺序从索引0开始获取元素。
3、如果尝试失败抛出TypeError异常
4、理解迭代协议
Python 迭代协议要求一个 __iter__() 方法返回一个特殊的迭代器,这个迭代器实现了 __next__() 方法,并通过 StopIteration异常标识迭代完成。
Eg: 如下代码,按照迭代协议描述:
# -*- coding:utf -*-
import re
import reprlib
RE_WORD= re.compile('\w+')
class Sentence:
def__init__(self, text):
self.text= text
self.words= RE_WORD.findall(text)
def__repr__(self):
return 'Sentence(%s)' %reprlib.repr(self.text)
def__iter__(self):
return SentenceIterator(self.words)
class SentenceIterator:
def__init__(self, words):
self.words= words
self.index= 0
def __next__(self):
try:
word = self.words[self.index]
except IndexError:
raise StopIteration()
self.index+= 1
return word
def__iter__(self):
return self
if __name__ == '__main__':
s = Sentence('helloworld')
it = iter(s)
print(it)
print(next(it))
print(next(it))
结果:
<__main__.SentenceIteratorobject at 0x03561F30>
hello
World
符合可迭代对象和迭代器的描述情况。
如果我们不按照这种协议的说明:__iter__ 函数不返回一个迭代器,使用别的函数返回迭代器情况会是什么。修改代码如下,并执行打印:
# -*- coding:utf -*-
import re
import reprlib
RE_WORD= re.compile('\w+')
class Sentence:
def__init__(self, text):
self.text= text
self.words= RE_WORD.findall(text)
def__repr__(self):
return 'Sentence(%s)' %reprlib.repr(self.text)
def__iter__(self):
return iter(self.words)
defshow_word(self):
return SentenceIterator(self.words)
class SentenceIterator:
def__init__(self, words):
self.words= words
self.index= 0
def __next__(self):
try:
word = self.words[self.index]
except IndexError:
raise StopIteration()
self.index+= 1
return word
def__iter__(self):
return self
if __name__ == '__main__':
s = Sentence('helloworld')
print(s.show_word())
print(next(s.show_word()))
forword in s.show_word():
print(word)
运行结果:
<__main__.SentenceIteratorobject at 0x03271250>
hello
hello
world
接着执行如下:
if __name__ == '__main__':
s = Sentence('helloworld')
it = iter(s)
print(it)
print(next(it))
print(next(it))
运行结果:
hello
world
因为 __iter__ 函数返回值是个list 类型,所以使用iter()函数依旧可以生成一个list_iterator。原始数据可迭代,使用iter()函数可生成一个迭代器
如果原始数据不可迭代,调用iter就会报错:
>>> s = 14
>>> s
14
>>>iter(14)
Traceback (mostrecent call last):
File "
iter(14)
TypeError: 'int'object is not iterable
以上两种方式是为了理解迭代对象和迭代器,实时上这种写法过于繁琐,使用生成器来实现迭代器:
# -*- coding:utf -*-
import re
import reprlib
RE_WORD= re.compile('\w+')
class Sentence:
def__init__(self, text):
self.text= text
self.words= RE_WORD.findall(text)
def__repr__(self):
return 'Sentence(%s)' %reprlib.repr(self.text)
def__iter__(self):
for i in self.words:
yield i
if __name__ == '__main__':
s = Sentence('helloworld')
it = iter(s)
print(it)
print(next(it))
print(next(it))
输出结果:
hello
world
使用生成器很大减少了繁琐的自己实现一个迭代器并且实现 __next__方法。
当然生成器除了使用: yield关键字以外还可以使用生成器表达式,类似于列表推导式。
# -*- coding:utf-8 -*-
def gen_():
print('start')
yield'a'
print('continue')
yield'b'
print('end.')
res1 =[x*3 for x in gen_()]
print(res1)
res2 =(x*3 for x in gen_())
print(res2)
输出结果:
start
continue
end.
['aaa', 'bbb']
列表推导式直接打印出来了所有的结果,而生成器表达式并没有,生成器表达式可以使用next()函数来输出结果。