太仓市质监站网址,优秀vi设计网站,一键免费创建论坛网站,一个网站添加多个网址一、核心要义
1. 使用iter内置函数处理可迭代对象的方式
2. 如何使用Python实现经典的迭代器模式
3. 生成器函数工作原理
4. 使用生成器函数或生成器表达式代替经典的迭代器
5. 使用yield from语句合并生成器
二、代码示例
1、遍历单词序列回顾
#!/usr/bin/env python
…一、核心要义
1. 使用iter内置函数处理可迭代对象的方式
2. 如何使用Python实现经典的迭代器模式
3. 生成器函数工作原理
4. 使用生成器函数或生成器表达式代替经典的迭代器
5. 使用yield from语句合并生成器
二、代码示例
1、遍历单词序列回顾
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2024/2/26 20:42
# Author : Maple
# File : 01-遍历单词序列回顾.py
# Software: PyCharm
from collections import abc
import re
import reprlibRE_WORDS re.compile(\w)
class Sentence:def __init__(self,text):self.text textself.words RE_WORDS.findall(text)def __getitem__(self, pos):return self.words[pos]def __len__(self):return len(self.words)def __repr__(self):return Sentences(%s) % reprlib.repr(self.text)class Foo:def __iter__(self):passif __name__ __main__:# 1. 迭代Sentence对象s Sentence(I love this word)s可迭代的原因1. 当迭代一个对象的时候,解释器会检查对象是否实现了__iter__方法,如果实现了,就调用它,获取一个迭代器2. 如果没有实现__iter__方法,但是实现了__getitem__方法,Python会创建一个迭代器,尝试按顺序(从索引0开始)获取元素3. 如果尝试失败,Python抛出TypeError异常,通常会提示C object is not itereblefor word in s:Ilovethiswordprint(word)# 2. Sentence对象是否可通过issubclass和isinstance测试# 虽然Sentence对象实现了 __getitem__,因为是可迭代的,但其实无法通过测试# 所以如果要判断一个对象是否可迭代,最好不要使用该方式,而是直接iter(对象),如果没有报错,就说明对象是可迭代的print(issubclass(Sentence,abc.Iterable)) # Falseprint(isinstance(s,abc.Iterable)) # False## 获取迭代器s iter(s)## 迭代迭代器中的元素for word in s:print(word)# 3.一个类只要实现了__iter__方法,那么其对象就是可迭代的,并且可以通过issubclass和isinstance测试f Foo()print(issubclass(Foo, abc.Iterable)) # Trueprint(isinstance(f, abc.Iterable)) # True
2、可迭代对象和迭代器
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2024/2/26 21:03
# Author : Maple
# File : 02-可迭代对象和迭代器.py
# Software: PyCharm
两者的定义和关系1.可迭代对象: 实现了__iter__方法2.迭代器: 实现了__iter__和__next__方法
import re
import reprlibRE_WORDS re.compile(\w)
1.利用__iter__方法定义一个类,当调用iter方法时,返回一个迭代器
2.对迭代器进行遍历的时候,不断调用next方法,返回迭代器中的每一个元素class Sentence:def __init__(self,text):self.text textself.words RE_WORDS.findall(text)def __iter__(self):return SentenceIterator(self.words)def __len__(self):return len(self.words)def __repr__(self):return Sentences(%s) % reprlib.repr(self.text)class SentenceIterator:定义迭代器:__iter__方法和__next__方法def __init__(self,words):self.words wordsself.index 0def __iter__(self):迭代器应该一直可以迭代,所以返回自身,在哪里会用到这个特性? return selfdef __next__(self):try:word self.words[self.index]except IndexError:raise StopIteration()self.index 1return wordif __name__ __main__:# 1. Sentence测试s Sentence(I love this world)for word in s:print(s)# 2.s2是一个迭代器## 2-1 直接调用迭代器类 生成一个迭代器print(******2-1 直接调用迭代器类 生成一个迭代器************)s2 SentenceIterator([we, are, the, world])print(s2:,s2)index 0for word in s2:weareindex 1if index 1:print(word)breakelse:print(word)## 2-2 调用迭代器的iter方法,返回迭代器本身print(******2-2 调用迭代器的iter方法,返回迭代器本身************)s3 iter(s2)print(s3:,s3)for word in s3:在2-1的基础上,继续迭代,直到迭代结束theworldprint(word)
3、生成器函数
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2024/2/26 21:42
# Author : Maple
# File : 03-生成器函数.py
# Software: PyCharm
对上一小节的Sentence进一步改造:__iter__方法不用返回一个迭代器.而是直接将其定义为一个生成器函数
--什么是生成器函数: 包含yield关键import re
import reprlibRE_WORDS re.compile(\w)# 利用生成器函数,实现Sentence类对象的可迭代(不用在__iter__方法中返回迭代器)
class Sentence1:def __init__(self,text):self.text textself.words RE_WORDS.findall(text)def __repr__(self):return Sentences(%s) % reprlib.repr(self.text)def __iter__(self):for word in self.words:yield wordreturndef __len__(self):return len(self.words)# 对Sentence1进一步改造:self.words不需要提前生成(是一个列表)
class Sentence2:def __init__(self,text):self.text textdef __repr__(self):return Sentences(%s) % reprlib.repr(self.text)def __iter__(self):# RE_WORDS.finditer(self.text)返回的是一个迭代器# 通过for循环遍历迭代器for match in RE_WORDS.finditer(self.text):yield match.group()return# 利用生成器表达式,进一步改造Sentence
class Sentence3:def __init__(self,text):self.text textdef __repr__(self):return Sentences(%s) % reprlib.repr(self.text)def __iter__(self):# 直接返回生成器表达式,与yield的作用相同return (match.group() for match in RE_WORDS.finditer(self.text))if __name__ __main__:# 1.Sentence1测试s Sentence1(I love this world)## 调用iter返回一个生成器s_iter iter(s)## 遍历生成器(本质就是一个迭代器)for word in s_iter:Ilovethiswordprint(word)# 2.Sentence2测试print(******2.Sentence2测试***********)s2 Sentence2(Please stay with me forerver)## 调用iter返回一个生成器s_iter2 iter(s2)## 遍历生成器(本质就是一个迭代器)for word in s_iter2:Pleasestaywithmeforerverprint(word)# 3.Sentence3测试print(******3.Sentence3测试***********)s3 Sentence3(Lets start study Python)## 调用iter返回一个生成器s_iter3 iter(s3)## 遍历生成器(本质就是一个迭代器)for word in s_iter3:LetsstartstudyPythonprint(word)
4、等差数列生成器
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2024/2/27 20:03
# Author : Maple
# File : 04-等差数列生成器.py
# Software: PyCharm# 自定义等差序列生成器
from decimal import Decimalclass ArithmeticProgression:def __init__(self,start,step,endNone):self.start startself.step stepself.end enddef __iter__(self):index 0result type(self.start self.step)(self.start)forever self.end is Nonewhile forever or result self.end:yield resultindex 1result self.start self.step * indexclass ArithmeticProgression2:def __init__(self,start,step,endNone):self.start startself.step stepself.end enddef __iter__(self):ap_gen itertools.count(self.start, self.step)if self.end is not None:ap_gen itertools.takewhile(lambda n: n self.end, itertools.count(self.start, self.step))# 直接返回迭代器return ap_genif __name__ __main__:# 1. 自定义等差序列生成器测试## 1-1: 起始值1,步长为0.5,末项是5(不包含)a1 ArithmeticProgression(1,0.5,5)for i in a1:1.01.52.02.53.03.54.04.5print(i)## 1-2: 起始值1,步长为Decimal(0.2),末项是2(不包含)a2 ArithmeticProgression(1, Decimal(.2),2)for i in a2:11.2000000000000000111022302461.4000000000000000222044604921.6000000000000000333066907391.800000000000000044408920985print(i)#2.利用系统自带的itertools模块生成等差数列print(*****2.利用系统自带的itertools模块生成等差数列********)import itertools## 2-1 注意:由于该模块方法并没有end参数,如果通过for循环遍历,会生成无穷的序列..直到内存爆掉g itertools.count(1,0.5)print(next(g)) # 1print(next(g)) # 1.5## 2-2 为了修复上面提到的弊端,可以利用# 该方法返回的是一个迭代器,然后接收两个参数当第二个迭代器中的元素,不满足第一个参数设置的条件时,会终止第二个迭代器迭代gen itertools.takewhile(lambda n: n 3,itertools.count(1,0.5))print(list(gen)) # [1, 1.5, 2.0, 2.5]# 3.利用itertools.takewhile改造ArithmeticProgressionprint(******3.利用itertools.takewhile改造ArithmeticProgression**********************)a3 ArithmeticProgression2(1, 0.5, 5)print(list(a3)) # [1, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5]a4 ArithmeticProgression2(1, Decimal(.2), 2)print(list(a4)) # [1, Decimal(1.200000000000000011102230246), Decimal(1.400000000000000022204460492), Decimal(1.600000000000000033306690738), Decimal(1.800000000000000044408920984)]
5、yield from
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2024/2/27 20:36
# Author : Maple
# File : 05-yield from.py
# Software: PyCharm
当生成器函数需要产出另一个生成器 生成的值,传统的解决方案是for循环嵌套def chain(*iterables):for it in iterables:for i in it:yield i# 利用yield from
def chain2(*iterables):for it in iterables:yield from itif __name__ __main__:#1.chain方法测试s ABCt tuple(range(3))# [A, B, C, 0, 1, 2]print(list(chain(s,t)))#2.chain2方法测试s EDFt tuple(range(3))# [A, B, C, 0, 1, 2]print(list(chain2(s, t))) # [E, D, F, 0, 1, 2]
6、可迭代的归约函数
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2024/2/27 20:45
# Author : Maple
# File : 06-可迭代的归约函数.py
# Software: PyCharmif __name__ __main__:print(all([1,2,3])) #Trueprint(all([1,0,3])) #Falseprint(any([1,2,3])) #Trueprint(any([1,0,3])) #Trueprint(any([0,0.0])) #Falseprint(any([])) #Falseg (n for n in [0,0.0,7,8])print(any(g)) #True
7、迭代器哨值
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Time : 2024/2/27 20:50
# Author : Maple
# File : 07-迭代器哨值.py
# Software: PyCharm
迭代器函数iter可以传入两个参数其中第一个必须是一个可调用对象,第二个就是哨值,当可调用对象返回这个值时,迭代器将停止迭代from random import randintdef f6():# 返回[1-6]区间的整数return randint(1,6)if __name__ __main__:# print(randint(1,6))f6_iter iter(f6,1)for i in f6_iter:# 如下结果表明,第三次迭代的值是1,然后迭代终止24print(i)