Python 迭代器与生成器
1. 迭代器 Iterator
什么是迭代器
-
迭代器是访问可迭代对象的工具
-
迭代器是指用 iter(obj) 函数返回的对象(实例)
-
迭代器可以用next(it)函数获取可迭代对象的数据
迭代器函数iter和****next
函数 | 说明 |
---|---|
iter(iterable) | 从可迭代对象中返回一个迭代器,iterable必须是能提供一个迭代器的对象 |
next(iterator) | 从迭代器iterator中获取下一个记录,如果无法获取一下条记录,则触发 |
迭代器说明
-
迭代器只能往前取值,不会后退
-
用iter函数可以返回一个可迭代对象的迭代器
迭代器示例:
# 示例 可迭代对象
L = [1, 3, 5, 7]
it = iter(L) # 从L对象中获取迭代器
next(it) # 1 从迭代器中提取一个数据
next(it) # 3
next(it) # 5
next(it) # 7
next(it) # StopIteration 异常
# 示例2 生成器函数
It = iter(range(1, 10, 3))
next(It) # 1
next(It) # 4
next(It) # 7
next(It) # StopIteration
"""
技能迭代器
技能管理器
"""
class SkillIterator:
def __init__(self,data):
self.__data = data
self.__index = -1
def __next__(self):
self.__index += 1
if self.__index > len(self.__data)-1:
raise StopIteration()
return self.__data[self.__index]
class SkillManager:
def __init__(self):
self.__skills = []
def add_skill(self,skill):
self.__skills.append(skill)
def __iter__(self):
return SkillIterator(self.__skills)
manager = SkillManager()
manager.add_skill('Python')
manager.add_skill('Java')
manager.add_skill('C++')
manager.add_skill('PHP')
# for skill in manager:
# print(skill)
# 实现for循环
it = manager.__iter__()
while True:
try:
# next(it)
item = it.__next__()
print(item)
except StopIteration:
break
迭代器的用途
- 迭代器对象能用next函数获取下一个元素
迭代器函数iter和****next 示例:
L = [2, 3, 5, 7]
it = iter(L)
# 访问列表中的所有元素
while True:
try:
print(next(it))
except StopIteration:
print("迭代器访问结束")
break
L = [2, 3, 5, 7]
for x in L:
print(x)
else:
print("迭代器访问结束")
2. 生成器
生成器是在程序运行时生成数据,与容器不同,它通常不会在内存中保留大量的数据,而是现用现生成。
-
yield 是一个关键字,用于定义生成器函数,生成器函数是一种特殊的函数,可以在迭代过程中逐步产生值,而不是一次性返回所有结果。
-
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
-
每次使用 yield 语句生产一个值后,函数都将暂停执行,等待被重新唤醒。
-
yield 语句相比于 return 语句,差别就在于 yield 语句返回的是可迭代对象,而 return 返回的为不可迭代对象。
-
然后,每次调用生成器的 next() 方法或使用 for 循环进行迭代时,函数会从上次暂停的地方继续执行,直到再次遇到 yield 语句。
生成器可以用算法动态的生成数据
生成器有两种
-
生成器函数
-
生成器表达式
生成器函数
含有yield 语句的函数是生成器函数,此函数调用回返回一个生成器对象,生成器也是可迭代对象
yield 表达式
生成器函数示例:
# 例1
## 定义一个生成器函数, 有 yield 的函数调用后回返回生成器对象
def myrange(stop):
i = 0
while i < stop:
yield i # 为 遍历次生产器的for 语句提供数据
i += 1
for x in myrange(5):
print('x=', x)
# 创建一个生成器对象
gen = myrange(5)
# 使用 next() 函数迭代生成器
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
print(next(gen))
# 例2
def Descendorder(n):
while n > 0:
yield n
n -= 1
# 创建生成器对象
generator = Descendorder(5)
# 通过迭代生成器获取值
print(next(generator))#5
print(next(generator))#4
# 使用 for 循环迭代生成器
for i in generator:
print('for循环:', i)#3 2 1
以上实例中,Descendorder 函数是一个生成器函数。它使用 yield 语句逐步产生从 n 到 1 的倒序数字。在每次调用 yield 语句时,函数会返回当前的倒序数字,并在下一次调用时从上次暂停的地方继续执行。
创建生成器对象并使用 next() 函数或 for 循环迭代生成器,我们可以逐步获取生成器函数产生的值。在这个例子中,我们首先使用 next() 函数获取前两个倒序数字,然后通过 for 循环获取剩下的三个倒序数
字。
生成器函数的优势是它们可以按需生成值,避免一次性生成大量数据并占用大量内存。此外,生成器还可以与其他迭代工具(如for循环)无缝配合使用,提供简洁和高效的迭代方式。
生成器表达式
- 语法:
( 表达式 for 变量 in 可迭代对象 [if 真值表达式])
-
作用
用推导式的形式创建一个生成器
-
示例
>>> [x ** 2 for x in range(1, 5)] # 列表解析(列表推导式)
[1, 4, 9, 16]
>>>
>>> (x ** 2 for x in range(1, 5)) # 生成器表达式
<generator object <genexpr> at 0x7f41dcd30a40>
>>> for y in (x ** 2 for x in range(1, 5)):
... print(y)
...
1
4
9
16
python 函数式编程
定义:用一系列函数解决问题。
-
函数可以赋值给变量,赋值后变量绑定函数。
-
允许将函数作为参数传入另一个函数。
-
允许函数返回一个函数。
1. 函数作为参数
- 将核心逻辑传入方法体,使该方法的适用性更广。
def func01():
print("func01执行")
# a = func01
# # print(a)
# a()
def func02():
print("func02执行")
# 通用
def func03(func):
print("func03执行")
func()
func03(func02)
func03(func01)
注释
a = func01 :
-
变量 a 现在指向 func01 函数对象。
-
a 不是函数的返回值,而是函数对象本身
print(a) :
- 打印 a ,输出 <function func01 at 0x…> ,表示 a 是一个函数对象,并显示其内存地址。赋值语句 a = func01 并不会执行 func01 函数,只是将函数对象赋值给 a 。调用 a() 或 func01()才会执行函数代码。
list01 = [4, 54, 56, 65, 67, 7]
# 需求1:定义函数,在列表中查找所有大于50的数字
def find01():
for item in list01:
if item > 50:
yield item
# 需求2:定义函数,在列表中查找所有小于10的数字
def find02():
for item in list01:
if item < 10:
yield item
# “封装” -- 分
def condition01(item):
return item > 50
def condition02(item):
return item < 10
# 通用
# “继承” - 隔
def find(func):
for item in list01:
# if item < 10:
# if condition02(item):
if func(item):
yield item
# "多态" - 做
for item in find(condition01):
print(item)
for item in find(condition02):
print(item)
总结
1、什么时候使用函数式编程思想?
很多的逻辑或者说核心点是不变的,大多数就是一致的,这个时候我们就可以使用函数式编程思想,可以很好的去定位这个逻辑【函数 式编程思想相对于面向对象编程思想,它更接近于算法】。
2、函数式编程思想替代了面向对象思想?
如果需求中存在多个逻辑变化点时,可以使用类来进行,因为面向对象中存在继承、重写。而函数式编程思想则是将变化点提取到函数 中,实现简单的逻辑。
**lambda ** 表达式
定义:是一种匿名函数
作用:
– 作为参数传递时语法简洁,优雅,代码可读性强。
– 随时创建和销毁,减少程序耦合度。
# 定义:
变量 = lambda 形参: 方法体
# 调用:
变量(实参)
说明:
– 形参没有可以不填
– 方法体只能有一条语句,且不支持赋值语句。
# 1. 有参数有返回值
# def func01(a,b):
# return a > b
#
# print(func01(10,20))
func01 = lambda a,b:a > b
print(func01(10,20))
# 2. 无参数有返回值
# def func02():
# return "ok"
#
# print(func02())
func02 = lambda :"ok"
print(func02())
# 3. 无参数无返回值
# def func03():
# print("ok")
#
# func03()
func03 = lambda :print("ok")
func03()
# 4. 有参数无返回值
# def func03(a):
# print(a)
#
# func03(100)
func03 = lambda a:print(a)
func03(100)
# 5. lambda 不支持赋值语句
# def func05(iterable):
# iterable[0] = 100
#
# list01 = [1]
# func05(list01)
# print(list01)
# func05 = lambda iterable: iterable[0] = 100 报错
# 6. lambda 不支持多条语句
# def func06(a,b):
# print(a)
# print(b)
#
# func06(10,20)
# func06 = lambda a,b: print(a);p
内置高阶函数
定义:将函数作为参数或返回值的函数。
常用:
(1)map(函数,可迭代对象)
- 使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。
(2)filter(函数,可迭代对象)
- 根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
(3)sorted(可迭代对象, key=函数, reverse=True)
- 排序,返回值为排序后的列表结果。
(4)max(可迭代对象, key = 函数)
- 根据函数获取可迭代对象的最大值。
(5)min(可迭代对象,key = 函数)
- 根据函数获取可迭代对象的最小值。
class Girl:
def __init__(self, name="", face_score=0, age=0,height=0):
self.name = name
self.face_score = face_score
self.age = age
self.height = height
def __str__(self):
return "%s-%d-%d-%d" % (self.name,self.face_score, self.age,self.height)
list_girl = [
Girl("双儿", 96, 22, 166),
Girl("阿珂", 100, 23, 173),
Girl("小郡主", 96, 22, 161),
Girl("方怡", 86, 27, 166),
Girl("苏荃", 99, 31, 176),
Girl("建宁", 93, 24, 163),
Girl("曾柔", 88, 26, 170),
]
# 1. map 映射
# 在美女列表中获取所有名称
# 类似于:select
for element in map(lambda item: item.name, list_girl):
print(element)
# 2. filter 过滤器
# 在美女列表中获取颜值大于90的所有美女
# 返回的是符合条件的对象的所以属性
# 类似于:find_all
for element in filter(lambda item: item.face_score > 90, list_girl):
print(element)
# 3. max/min
# 在美女列表中获取颜值最高的美女
# 类似于:get_max
print(max(list_girl,key = lambda item:item.face_score))
print(min(list_girl,key = lambda item:item.face_score))
# 4.sorted 排序
# 注意:没有改变原有列表,而是返回新的
# 升序
for item in sorted(list_girl,key = lambda item:item.height):
print(item)
# 降序
for item in sorted(list_girl,key = lambda item:item.height,reverse=True):
print(item)