导语:本文章记录了本人在学习Python基础之控制流程篇的重点知识及我的心得,打算入门Python的朋友们能够来一块儿学习并交流。
本文重点:python
一、掌握可迭代的对象的定义;
二、掌握可迭代对象、迭代器与生成器之间的关系和异同;
三、熟悉标准库中生成器。
可迭代的对象
:使用iter内置函数能够获取迭代器的对象。若是对象实现了能返回迭代器的__iter__方法,那么对象就是可迭代的。若是没有实现__iter__而实现了__getitem__方法,而且其参数是从零开始的索引,这种对象如序列也是可迭代的。向后兼容
:之因此任何Python序列可迭代是为了向后兼容。ssh
当解释器须要迭代对象时,会自动调用iter(x):函数
标准的序列都实现了__iter__方法,这是鸭子类型的极端形式。
在白鹅类型中,只要对象实现了__iter__方法,那么它就是可迭代的对象。学习
注意:
(1)只有实现了__iter__方法的对象能经过子类测试issubclass(Object,abc.Iterator)
(2)检查对象可否迭代最准确的方法是调用iter(x)函数
,若是不可迭代再处理TypeError。由于iter(x)会考虑到实现__getitem__方法的部分可迭代对象。测试
迭代器:用于从集合中取出元素的对象。
迭代器的功能:用于支持下列操做spa
迭代器的接口协议
:code
迭代器特色:orm
可迭代
。因为Python中的迭代器实现了__iter__方法,所以也能够迭代。易耗损
。迭代器通过一次逐次取值的循环后便耗尽了。若想再次迭代须重建迭代器。迭代器检查方式:调用isinstance(object,abc.Iterator)。
检查原理:归结于Iterator.__subclasshook__方法。不管对象所属的类是Iterator的真实子类仍是虚拟子类,都可以检查。协程
Python从可迭代的对象中获取迭代器
。可迭代的对象不是迭代器
。迭代器模式:按需一次获取一个数据项。
扫描内存中放不下的数据集时,咱们要找到一种惰性获取数据项的方式,即按需一次获取一个数据项。这就是迭代器模式(Iterator pattern) 。
迭代器模式的用途:对象
访问一个聚合对象的内容而无需暴露它的内部表示
;支持对聚合对象的多种遍历
;为遍历不一样的聚合结构提供一个统一的接口(即支持多态迭代)
。下面构造一个能够处理文本匹配并迭代的实例:
import reprlib import re reword=re.compile('\w+') #初版:迭代器模式 class Sentence: def __init__(self,text): self.text=text self.words=reword.findall(text) def __repr__(self): return "Sentence({})".format(reprlib.repr(self.text)) def __iter__(self): return SentenceIterator(self.words) class SentenceIterator: def __init__(self,text): self.words=text 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 title=Sentence('We have a dream!') print(title) for i in title: print(i)
输出: Sentence('We have a dream!') We have a dream
注意:
(1)不要把迭代器接口应用到可迭代对象上,这是常见的反模式
。
(2)可迭代对象必须实现__iter__方法,但不能实现__next__方法
。
生成器:用于按需生成元素的对象。在Python社区中大多数时候都把迭代器和生成器视做同一律念。
生成器函数:拥有yield关键字的Python函数。
生成器表达式:制造生成器的工厂,支持惰性产值。
生成器工厂函数:返回生成器的函数,定义体中能够没有yield关键字。
生成器函数与生成器表达式优势比较:
Tips:生成器表达式做为单参数传入时无须写一对括号,而多参数时须将小括号加上。
实例1:经过一个问候同窗的代码来了解生成器函数是如何工做的
def gen(): print("start") yield "Jack" print("continue") yield "Dennis" print("end") for i in gen(): print("Hello ",i)
输出: start Hello Jack continue Hello Dennis end
原理分析:不难发现,for循环中操做的对象是生成器中的yield生成的值。缘由在于,生成器是迭代器,会生成传给yield关键字的表达式的值。
注意:无论有没有return语句,生成器函数都不会抛出StopIteration异常,而是在生成所有值以后直接退出。
实例2:生成器函数改进版
import reprlib import re reword=re.compile('\w+') #第二版:生成器函数 class Sentence: def __init__(self,text): self.text=text self.words=reword.findall(text) def __repr__(self): return "Sentence({})".format(reprlib.repr(self.text)) def __iter__(self): for i in self.words: yield i return title=Sentence('We have a dream!') print(title) for i in title: print(i)
import reprlib import re reword=re.compile('\w+') #第三版:生成器表达式 class Sentence: def __init__(self,text): self.text=text def __repr__(self): return "Sentence({})".format(reprlib.repr(self.text)) def __iter__(self): return (match.group() for match in reword.finditer(self.text)) title=Sentence('We have a dream!') print(title) for i in title: print(i)
Tips:re.finditer函数是re.findall函数的惰性版本,返回的不是列表而是一个生成器,按需惰性生成元素。
过滤
的生成器函数: itertools.takewhile/compress/dropwhile/filter/filterfalse/islice/映射
的生成器函数: 内置的 enumerate/map itertools.accumulate/starmap合并
的生成器函数:itertools.chain/from_iterable/product/zip_longest/ 内置的 zip扩展输入的可迭代对象
: itertools.combinations/combinations_with_replacement/count/cycle/permutations/repeat产出输入可迭代对象的所有元素,以某种方式排列
:itertools.groupby/tee/ 内置的 reversed一、归约函数:接受可迭代对象并返回单个结果的函数。这里的all和any函数会短路,即一旦得出结果立刻中止迭代。