Python基础之迭代器、生成器
一、迭代器:
1、迭代:每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值。例如:循环获取容器中的元素。
2、可迭代对象(iterable):
1)定义:具有__iter__函数的对象,可以返回迭代器对象。
2)语法:
3)原理:
3、迭代器对象(iterator):
1)定义:可以被next()函数调用并返回下一个值的对象。
2)语法:
3)说明及作用:
二、生成器(generator):
三、生成器函数:
6、内置生成器:
7、生成器表达式:
四、基础代码:
代码1:
"""
可迭代对象:具有__iter__()方法,可以返回迭代器的对象.
"""
list01 = [2,434,5,6,8] # for item in list01:
# print(item) # 面试题:
# 能够被for循环的条件是:可迭代对象(具有__iter__()方法的对象) # for循环原理
# 1. 获取迭代器对象
# 2. 循环迭代(调用迭代器的__next__方法)
# 3. 捕获StopIteration异常 #1.
# iterator = list01.__iter__()
#2.
# item = iterator.__next__()
# print(item)
#
# item = iterator.__next__()
# print(item)
#
# item = iterator.__next__()
# print(item)
#
# item = iterator.__next__()
# print(item)
#
# item = iterator.__next__() # 最后一次
# print(item)
# 3.
# item = iterator.__next__()# StopIteration
# print(item) # 1. 获取迭代器对象
iterator = list01.__iter__()
while True:
try:# 如果获取了全部元素,则执行except
# 2. 获取下一个元素(迭代过程)
item = iterator.__next__()
print(item)
# 3.停止迭代(StopIteration 错误)
except StopIteration:
break # 跳出循环体
代码2:
"""
迭代器
""" class Skill:
pass class SkillIterator:
"""
技能迭代器
"""
def __init__(self, target):
self.target = target
self.index = 0 def __next__(self): # 如果索引越界 则抛出异常
if self.index > len(self.target) - 1:
raise StopIteration()
# 返回下一个元素
item = self.target[self.index]
self.index += 1
return item class SkillManager:
"""
可迭代对象
"""
def __init__(self, skills):
self.skills = skills def __iter__(self):
# 创建迭代器对象 传递 需要迭代的数据
return SkillIterator(self.skills) #---------------以下是客户端代码--------------------- manager = SkillManager([Skill(), Skill(), Skill()])
# for item in manager.skills:
for item in manager:# 获取manager对象中列表元素(获取manager对象的聚合类型对象元素)
print(item)
# iterator = manager.__iter__()
# while True:
# try:
# item = iterator.__next__()
# print(item)
# except:
# break
代码3:
"""
迭代器 --> yield """ class Skill:
pass # class SkillIterator:
# """
# 技能迭代器
# """
# def __init__(self, target):
# self.target = target
# self.index = 0
#
# def __next__(self):
# if self.index > len(self.target) - 1:
# raise StopIteration()
# item = self.target[self.index]
# self.index += 1
# return item class SkillManager:
def __init__(self, skills):
self.skills = skills # def __iter__(self):
# return SkillIterator(self.skills) def __iter__(self):
"""
执行过程:
1.调用__iter__()方法不执行
2.调用__next__()方法时执行,到yield语句暂时离开.
3.再次调用__next__()方法时,从上次离开的代码开始执行,到yield语句暂时离开
4. 待执行完方法体,抛出StopIteration异常. 原理:如果方法体中包含yield关键字,那么会自动生成迭代器对象.
生成迭代器代码的大致规则:
1. 将yield关键字以前的代码,放到__next__方法中.
2. 将yield关键字以后的数据,作为__next__方法的返回值
"""
# print("准备返回第一个元素")
# yield self.skills[0] # 暂时离开点 再次执行点
#
# print("准备返回第二个元素")
# yield self.skills[1]
#
# print("准备返回第三个元素")
# yield self.skills[2] for item in self.skills:
yield item #---------------以下是客户端代码--------------------- manager = SkillManager([Skill(), Skill(), Skill()]) # for item in manager:
# print(item) iterator = manager.__iter__()
while True:
try:
item = iterator.__next__()
print(item)
except Exception as e:
print(e)
break
代码4:
"""
yield --> 生成器函数
""" # class MyRange:
# def __init__(self, stop):
# self.stop = stop
#
# def __iter__(self):
# start = 0
# while start < self.stop:
# yield start
# start += 1
#
# for item in MyRange(5):
# print(item) # 生成器函数
def my_range(stop):
start = 0
while start < stop:
yield start
start += 1 # for item in my_range(5):
# print(item) iter01 = my_range(5)
for item in iter01:
print(item)
代码5:
"""
内置生成器:enumerate
""" list01 = ["a", "b", "c"] for item in enumerate(list01):
# (索引,元素)
print(item) for index, element in enumerate(list01):
print(index, element) # 练习:参照上述代码,自定义函数,my_enumerate.
# 10:46 def my_enumerate(target):
index = 0
for item in target:
yield (index,item)
index += 1 for item in my_enumerate(list01):
print(item) for index, element in my_enumerate(list01):
print(index, element)
代码6:
"""
内置生成器:zip
""" list02 = [101,102,103]
list03 = ["张三丰","张无忌","赵敏"]
for item in zip(list02,list03):
# (101, '张三丰')
print(item) #练习:参照上述代码,自定义函数,my_zip 11:05
def my_zip(list01,list02):
for index in range(len(list01)):
# yield (list01[index],list02[index])
yield list01[index], list02[index] for item in my_zip(list02,list03):
# (101, '张三丰')
print(item)
代码7:
"""
生成器表达式
""" list01 = [2,3,4,6]
# result = []
# for item in list01:
# result.append(item ** 2) # 列表推导式[] 字典推导式 {键:值 for ...} 集合 { for ... }
result = [item ** 2 for item in list01]
print(result) # def fun01(target):
# for item in target:
# yield item ** 2
# 生成表达式
# for item in fun01(list01):
# print(item) result = (item ** 2 for item in list01)
for item in result:
print(item)
五、练习实例:
练习1:
# 练习1:("悟空","八戒","沙僧","唐僧")
# 使用while + 迭代器 获取元组所有元素
t01 = ("悟空", "八戒", "沙僧", "唐僧")
iterator = t01.__iter__()
while True:
try:
item = iterator.__next__()
print(item)
except:
break # 练习2:{"张三丰":101,"张无忌":102,"赵敏":102}
# 不使用for循环,获取字典所有元素. d01 = {"张三丰": 101, "张无忌": 102, "赵敏": 102}
iterator = d01.__iter__()
while True:
try:
key = iterator.__next__()
print(key, d01[key])
except:
break
练习2:
"""
练习:迭代员工管理器对象 """ class Employee:
pass class EmployeeIterator:
"""
迭代器
"""
def __init__(self, target):
self.target = target
self.index = 0 def __next__(self):
if self.index > len(self.target) - 1:
raise StopIteration()
item = self.target[self.index]
self.index += 1
return item # 可迭代对象
class EmployeeManager:
def __init__(self, employees):
self.all_employee = employees def __iter__(self):
# 返回迭代器
return EmployeeIterator(self.all_employee) manager = EmployeeManager([Employee(), Employee()]) # 需求:for循环自定义类的对象
# for item in manager:
# print(item) # iterator = manager.__iter__()
while True:
try:
item = iterator.__next__()
print(item)
except:
break
练习3:
"""
参照下列代码,定义MyRange类,实现相同效果. """ # 15:40
class MyRangeIterator:
def __init__(self, stop):
self.stop = stop
self.start = 0 def __next__(self):
if self.start + 1 > self.stop:
raise StopIteration()
temp = self.start
self.start += 1
return temp class MyRange:
def __init__(self, stop):
self.stop = stop def __iter__(self):
# 创建迭代器对象
return MyRangeIterator(self.stop) # for item in range(5):
# print(item)# # for item in MyRange(5):
# print(item)#0 1 2 3 4 iterator = MyRange(5)
for item in iterator:
print(item) # # iterator = iterator.__iter__()
# while True:
# try:
# item = iterator.__next__()
# print(item)
# except:
# break
练习4:
"""
改造为yield实现
""" class Employee:
pass # class EmployeeIterator:
# """
# 迭代器
# """
# def __init__(self, target):
# self.target = target
# self.index = 0
#
# def __next__(self):
# if self.index > len(self.target) - 1:
# raise StopIteration()
# item = self.target[self.index]
# self.index += 1
# return item # 可迭代对象
class EmployeeManager:
def __init__(self, employees):
self.all_employee = employees # def __iter__(self):
# # 返回迭代器
# return EmployeeIterator(self.all_employee) def __iter__(self):
for item in self.all_employee:
yield item manager = EmployeeManager([Employee(), Employee()]) # 需求:for循环自定义类的对象
# for item in manager:
# print(item) # iterator = manager.__iter__()
while True:
try:
item = iterator.__next__()
print(item)
except:
break
练习5:
"""
改造为yield实现
""" # class MyRangeIterator:
# def __init__(self, stop):
# self.stop = stop
# self.start = 0
#
# def __next__(self):
# if self.start + 1 > self.stop:
# raise StopIteration()
# temp = self.start
# self.start += 1
# return temp class MyRange:
def __init__(self, stop):
self.stop = stop # def __iter__(self):
# # 创建迭代器对象
# return MyRangeIterator(self.stop) def __iter__(self):
start = 0
while start < self.stop:
yield start
start += 1 iterator = MyRange(5)
# for item in iterator:
# print(item) # iterator = iterator.__iter__()
while True:
try:
item = iterator.__next__()
print(item)
except:
break
练习6:
"""
生成器函数练习
体会:方法/函数,需要向外返回多个结果时,使用生成器函数.
惰性操作/延迟操作 (生成器函数的"循环(next)一次,计算一次,返回一次") """
list01 = [23,3,4,556,677,68,8,98,98]
# 练习1:在list01中,挑出所有偶数.
# 要求:1)使用生成器函数实现
def get_even01(target):
for item in target:
if item % 2 == 0:
yield item iter01 = get_even01(list01)# 没有执行方法体
for item in iter01:# 循环(next)一次,计算一次,返回一次
print(item) # def get_even02(target):
# result = []
# for item in target:
# if item % 2 == 0:
# result.append(item)
# return result
#
# iter01 = get_even02(list01)# 执行方法体,将所有结果存在内存中.
# for item in iter01:
# print(item) # 练习2:定义函数,选出所有女同学.
class Student:
def __init__(self,name,sex,age,score):
self.name = name
self.sex = sex
self.age = age
self.score = score def __str__(self):
return "%s--%s--%d--%d"%(self.name,self.sex,self.age,self.score) list_stu = [
Student("张无忌","男",28,82),
Student("赵敏","女",25,95),
Student("周芷若","女",26,88),
] def find_woman(target):
for item in target:
if item.sex == "女":
yield item for item in find_woman(list_stu):
print(item) # 练习3:选出所有成绩大于90的学生
def find_by_score(target):
for item in target:
if item.score > 90:
yield item for item in find_by_score(list_stu):
print(item)
练习7:
# 1.创建技能类(编号,技能名称,冷却时间,攻击力,消耗法力)
# 创建技能列表.
# -- 定义函数:查找编号是101的技能对象
# -- 定义函数:查找冷却时间为0的所有技能对象
# -- 定义函数:查找攻击力大于5的所有技能对象
# -- 定义函数:查找攻击力大于10,并且不需要消耗法力的所有技能. class SkillData:
def __init__(self, id, name, cd, atk, costSP):
self.id = id
self.name = name
self.cd = cd
self.atk = atk
self.costSP = costSP list_skills = [
SkillData(101, "降龙十八掌", 60, 10, 5),
SkillData(102, "如来神掌", 50, 15, 0),
SkillData(103, "六脉神剑", 0, 20, 8),
SkillData(104, "一阳指", 0, 50, 15),
SkillData(105, "冷酷追击", 15, 30, 9),
] # 因为需要查找的结果只有一个,所以使用return返回数据.
# 比使用yield返回数据,在调用者看来,更加方便吧.
def find_demo01(target):
for item in target:
if item.id == 101:
return item s01 = find_demo01(list_skills)
print(s01.id) def find_demo02(target):
for item in target:
if item.cd == 0:
yield item result = find_demo02(list_skills)
# 不能获取指定结果
# 因为:此时生成器函数并没有计算处结果.
# print(result[1].name)
# for item in result:
# print(item.name) result = find_demo02(list_skills)
# 通过生成器创建列表
# 由惰性查找(优势:节省内存) 转换为 立即查找(优势:灵活获取结果)
result = list(result)
# print(result[1].name) def find_demo03(target):
for item in target:
if item.atk > 5:
yield item # 调用生成器函数,创建迭代器对象
result = find_demo03(list_skills)
for item in result:# __next__()
print(item.name) print("---------------")
# 如果没有下一行代码,再次for使用过的生成器对象,不会再有结果.
# result = find_demo03(list_skills)
for item in result:
print(item.name) # for item in find_demo03(list_skills):
# .... def find_demo04(target):
for item in target:
if item.atk > 10 and item.costSP == 0:
yield item for item in find_demo04(list_skills):
print(item.name)
练习8:
list02 = [2,3,4,6]
# 练习:使用列表推导式,与生成器表达式,获取list02中,大于3的数据. result01 = [item for item in list02 if item > 3 ] # 本行代码:执行所有操作,保存所有结果
result02 = (item for item in list02 if item > 3 ) # 本行代码:返回生成器对象 for item in result01:# 从结果中获取数据
print(item) for item in result02:# 循环一次,计算一次,返回一次
print(item)
练习9:
# 1.创建技能类(编号,技能名称,冷却时间,攻击力,消耗法力)
# 创建技能列表.
# -- 定义函数:查找冷却时间为0的所有技能对象
# -- 定义函数:查找攻击力大于5的所有技能对象
# -- 定义函数:查找攻击力大于10,并且不需要消耗法力的所有技能.
# 使用列表推导式,与生成器表达式完成
# 通过断点调试,审查程序执行过程,体会两项技术的差异. class SkillData:
def __init__(self, id, name, cd, atk, costSP):
self.id = id
self.name = name
self.cd = cd
self.atk = atk
self.costSP = costSP def __str__(self):
return self.name list_skills = [
SkillData(101, "降龙十八掌", 60, 10, 5),
SkillData(102, "如来神掌", 50, 15, 0),
SkillData(103, "六脉神剑", 0, 20, 8),
SkillData(104, "一阳指", 0, 50, 15),
SkillData(105, "冷酷追击", 15, 30, 9),
] # def find_demo02(target):
# for item in target:
# if item.cd == 0:
# yield item result01 = (item for item in list_skills if item.cd == 0)
result02 = [item for item in list_skills if item.cd == 0] for item in result01:
print(item) for item in result02:
print(item) # def find_demo03(target):
# for item in target:
# if item.atk > 5:
# yield item result01 = (item for item in list_skills if item.atk > 5)
result02 = [item for item in list_skills if item.atk > 5] for item in result01:
print(item) for item in result02:
print(item) # def find_demo04(target):
# for item in target:
# if item.atk > 10 and item.costSP == 0:
# yield item
result01 = (item for item in list_skills if item.atk > 10 and item.costSP == 0)
result02 = [item for item in list_skills if item.atk > 10 and item.costSP == 0] for item in result01:
print(item) for item in result02:
print(item)
Python基础之迭代器、生成器的更多相关文章
- python基础6 迭代器 生成器
可迭代的:内部含有__iter__方法的数据类型叫可迭代的,也叫迭代对象实现了迭代协议的对象 运用dir()方法来测试一个数据类型是不是可迭代的的. 迭代器协议是指:对象需要提供next方法,它要么返 ...
- python基础(9)-迭代器&生成器函数&生成器进阶&推导式
迭代器 可迭代协议和迭代器协议 可迭代协议 只要含有__iter__方法的对象都是可迭代的 迭代器协议 内部含有__next__和__iter__方法的就是迭代器 关系 1.可以被for循环的都是可迭 ...
- (转)python基础之迭代器协议和生成器(一)
一 递归和迭代 二 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前 ...
- Python基础(冒泡、生成器、迭代器、列表与字典解析)
一.冒泡算法 冒泡算法,给定一组数据,从大到小排序或者从小到大排序,就像气泡一样 原理: 相邻的两个对象相比,大的放到后面,交换位置 交换位置通过a,b=b,a来实现 1.我们可以通过for循环来根 ...
- Python基础之迭代器和生成器
阅读目录 楔子 python中的for循环 可迭代协议 迭代器协议 为什么要有for循环 初识生成器 生成器函数 列表推导式和生成器表达式 本章小结 生成器相关的面试题 返回顶部 楔子 假如我现在有一 ...
- python基础之 迭代器回顾,生成器,推导式
1.迭代器回顾 可迭代对象:Iterable 可以直接作用于for循环的对象统称为可迭代对象:Iterable.因为可迭代对象里面存在可迭代协议,所以才会被迭代 可迭代对象包括: 列表(list) 元 ...
- 7th,Python基础4——迭代器、生成器、装饰器、Json&pickle数据序列化、软件目录结构规范
1.列表生成式,迭代器&生成器 要求把列表[0,1,2,3,4,5,6,7,8,9]里面的每个值都加1,如何实现? 匿名函数实现: a = map(lambda x:x+1, a) for i ...
- python基础之迭代器协议和生成器
迭代器和生成器补充:http://www.cnblogs.com/luchuangao/p/6847081.html 一 递归和迭代 略 二 什么是迭代器协议 1.迭代器协议是指:对象必须提供一个ne ...
- python基础8 -----迭代器和生成器
迭代器和生成器 一.迭代器 1.迭代器协议指的是对象必须提供一个next方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代 (只能往后走不能往前退) 2. ...
- Python基础4 迭代器,生成器,装饰器,Json和pickle 数据序列化
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需 ...
随机推荐
- 【easy】438.Find All Anagrams in a String 找出字符串中所有的变位词
Input: s: "abab" p: "ab" Output: [0, 1, 2] Explanation: The substring with start ...
- 关于because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified报错的解决方案
我是采用代理模式的aspectj <plugin> <groupId>org.apache.maven.plugins</groupId> <artifact ...
- Python 猜数游戏
import random//引用随机数rand=random.randint(0,99)t=0while 1: //用t来记录使用次数 t+=1 //自行输入一个随机数 aNumber=int(in ...
- Python安装xlrd和xlwt的步骤以及使用报错的解决方法
一.安装xlrd和xlwt功能模块步骤 1.使用python -V查看python的版本号,并查看python安装环境,是否安装成功: 2.可以通过官网(python官网:https://pypi ...
- 强连通分量Kosaraju
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #i ...
- Git 的使用(皮毛))
1.安装git 软件(下一步直到完成) 2.码云注册(保存代码) 3.创建代码托管仓库 4.创建文件夹 5.写东西并提交到码云 1.在某个文件夹下写东西 2.写完之后在此文件夹下鼠标右键,并选择[gi ...
- .net基础学java系列(五)慢性自杀 之 沉沦在IDE中
最近在慢学习IDEA,总是喜欢与Visual Studio! 其实,对于Visual Studio,它的官方(https://docs.microsoft.com/zh-cn/visualstudio ...
- 物联网框架ServerSuperIO.Core(.netcore)跨平台,一套设备驱动通吃嵌入式、上位机、云服务
1. 概述... 2 2. ServerSuperIO.Core跨平台开发环境... 2 3. ServerSuperIO.Core特点... 2 4. Ser ...
- Redis 缓存失效和回收机制
本文及后续文章,Redis版本均是v3.2.8 一.内存回收策略 maxmemory配置用于配置Redis存储数据时指定限制的内存大小.我们可以通过redis.conf配置或者使用CONFIG SET ...
- Javascript 堆栈的模拟
栈(stack)又名堆栈,它是一种运算受限的线性表.其限制是仅允许在表的一端进行插入和删除运算.这一端被称为栈顶,相对地,把另一端称为栈底.向一个栈插入新元素又称作进栈.入栈或压栈,它是把新元素放到栈 ...