day17
一、迭代
1、迭代器对象iterator
(1)定义
定义:可以被next()函数调用并返回下一个值的对象。
需求:迭代自定义对象。
(2)语法
class 迭代器类名:
def init(self, 聚合对象):
self.聚合对象= 聚合对象
def next(self):
if 没有元素:
raise StopIteration
return 聚合对象元素
说明:聚合对象通常是容器对象。
作用:使用者只需通过一种方式,便可简洁明了的获取聚合对象中各个元素,而又无需了解其内部结构。
(3)演示
class StudentIterator: # 学生迭代器(可迭代对象)
def __init__(self,data):
self.__data = data
self.__index = -1
def __next__(self):
if self.__index == len(self.__data)-1:
raise StopIteration()
self.__index += 1
return self.__data[self.__index]
class StudentController: # 学生控制器
def __init__(self):
self.__list_student = []
def add_student(self, stu):
self.__list_student.append(stu)
def __iter__(self):
return StudentIterator(self.__list_student)
controller = StudentController()
controller.add_student("赵敏")
controller.add_student("张无忌")
controller.add_student("周芷若")
for item in controller:
print(item)
# iterator = controller.__iter__()
# while True:
# try:
# item = iterator.__next__()
# print(item)
# except StopIteration:
# break
(4)迭代器(过渡)
class StudentController: # 学生控制器
def __init__(self):
self.__list_student = []
def add_student(self, stu):
self.__list_student.append(stu)
def __iter__(self):
# 产生迭代器代码的大致思想:
# 1、将yield之前的代码存到__next__函数中
# 2、将yield之后的数据作为__next__返回值
index = 0
yield self.__list_student[index] # yield:产生
index += 1
yield self.__list_student[index]
index += 1
yield self.__list_student[index]
controller = StudentController()
controller.add_student("赵敏")
controller.add_student("下基层")
controller.add_student("跟他说")
# for item in controller:
# print(item)
iterator = controller.__iter__()
while True:
try:
item = iterator.__next__()
print(item)
except StopIteration:
break
二、生成器generator
1、生成器函数
(1)语法
#创建
def 函数名():
yield 数据
#调用
for 变量名 in 函数名():
语句
(2)说明
调用生成器函数将返回一个生成器对象,不执行函数体。
yield翻译为”产生”或”生成”。
(3)执行过程
a. 调用生成器函数会自动创建迭代器对象。
b. 调用迭代器对象的next()方法时才执行生成器函数。
c. 每次执行到yield语句时返回数据,暂时离开。
d. 待下次调用next()方法时继续从离开处继续执行。
(4)演示
def my_range(stop):
number = 0
while number < stop:
yield number
number += 1
for number in my_range(5):
print(number) # 0 1 2 3 4
(5)应用
函数向外返回多个结果,使用yield
函数向外返回单个结果,使用return
'''
需求:定义函数,在list01中查找所有奇数
'''
list01 = [43,4,54,56,67,7,87]
# --传统思想:创建容器存储所有结果
# 缺点:占用空间过多
def find_odd():
list_result = []
for number in list01:
if number % 2 :
list_result.append(number)
return list_result
result = find_odd()
for item in result:
print(item)
# --生成器思想:循环一次,计算一次,返回一次
# 优点:几乎不占内存
def find_odds():
for number in list01:
if number % 2:
yield number
# 调用函数,返回值是生成器对象(迭代器__next__),负责推算数据
result = find_odds()
for item in result:
print(item)
2、 内置生成器
(1)函数enumerate
作用:在遍历容器时,同时获取元素和其索引,将索引与元素组合为一个元组。
缺点:不能跳着走,不够灵活。
list01 = [54,45,54,6,7,8]
# 索引,元素 快捷键:itere + 回车
for i,item in enumerate(list01): # 可读可改
if item > 10:
list01[i] = 0
(2)函数zip
作用:将两个容器索引相同的值压缩成一个元组。
语法:
生成器 = zip(可迭代对象1,可迭代对象2)
for 元组 in 生成器:
list01 = ["张无忌","赵敏","周芷若","金毛狮王"]
list02 = [101,102,103,104]
for item in zip(list01,list02):
print(item)
map = [
[2, 0, 0, 2],
[2, 0, 2, 0],
[2, 2, 2, 2],
[4, 0, 2, 2]
]
# new_map = []
# for item in zip(map[0],map[1],map[2],map[3]):
# new_map.append(list(item))
# print(new_map)
# new_map = []
# for item in zip(*map):
# new_map.append(list(item))
new_map = [list(item) for item in zip(*map)]
print(new_map)
3、生成器表达式
(1)与列表表达式的区别
语法 | 优点 | 缺点 | |
---|---|---|---|
生成器表达式 | 生成器 = (变量 for 变量 in 可迭代对象 if 条件) | 节省内存 | 元素只读,只能使用一次,不支持索引切片 |
列表表达式 | 列表表达式= [变量 for 变量 in 可迭代对象 if 条件] | 元素可读可写,可以反复使用,使用索引切片 | 占用内存过多 |
(2)演示
list01 = [31,432,65,2,5,1]
# result = [item for item in list01 if item % 2]
result = (item for item in list01 if item % 2)
for item in result:
print(item)