Python迭代器和生成器
1.Python迭代器和生成器
1.1迭代器
- 访问可迭代对象的工具 iter(obj)返回对象(实例) next(it)获取下一个可迭代对象的值
- 迭代器只能往前不能后退
- 用iter函数可以返回一个可迭代对象的迭代器
- 用next可以获得迭代器的下一个值
1.2生成器
生成函数:
yield: 逐步生成值,不会一次返回多个值。 与return相比,yield返回的是可迭代对象,return不是。 当next()或for循环调用yield时,yield都会从上次停止的地方开始。
# 可迭代的对象
L = list(range(10))
it = iter(L)
# print(iter(L))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# print(next(it))
# #print(next(it))超出容量报错
while True:
try:
print(next(it))
except:
print('迭代结束')
break
list01 = list(range(10))
#需求:将大于5的数取出
#需求2:查找奇数
'''
解题方法一:一次达到目的
'''
def find01():
for item in list01:
if item > 5:
yield item
item += 1
def find02():
for item in list01:
if item %2 == 1:
yield item
item +=1
for data in find01():
print(data)
print('111111')
for data in find02():
print(data)
print('------')
'''
封装-分 把不同的数据分割出来
'''
def condition01(it):
return it > 5
def condition02(it):
return it %2 == 1
'''
继承-隔 把相同的数据融合在一起
'''
def find(func):
for ite in list01:
if func(ite):
yield ite
'''
做-多态 实现不同的任务
'''
for data in find(condition01):
print(data)
print('---')
for data in find(condition02):
print(data)
1.3生成器表达式
语法:(表达式 for 变量 in 可迭代对象 [if 真值表达式])
#生成器对象 生成器和迭代器一样可以配套for循环语句使用
def myrange(stop):
i = 0
while i<stop:
yield i
i += 1
#print(myrange(10))
#print(next(myrange(10)))
for x in myrange(10):
print(x)
Python函数式编程:
用一系列函数解决问题。
- 函数可以赋值给变量,赋值后变量绑定函数。
- 允许将函数作为参数传入另一个函数。
- 允许函数返回一个函数。
1.函数作为参数
将核心逻辑传入方法体
1.1lambda表达式
一种匿名函数
- 作为参数传递时语法简洁,优雅,代码可读性强。
- 随时创建和销毁,减少程序耦合度。
定义: 变量 = lambda 形参: 方法体
调用: 变量(实参)
1.2内置高阶函数
将函数作为或返回值的函数
- map(函数,可迭代对象) - 使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。
- filter(函数,可迭代对象) - 根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
- sorted(可迭代对象, key=函数, reverse=True) - 排序,返回值为排序后的列表结果。
- max(可迭代对象, key = 函数) - 根据函数获取可迭代对象的最大值。
- min(可迭代对象,key = 函数) - 根据函数获取可迭代对象的最小值。
class Girl:
list_girl = []# 类属性 存放所有美女信息
def __init__(self,name,outlook,age,height):
self.name = name
self.outlook = outlook
self.age = age
self.height = height
# print(self)
#将实例对象存入列表中,目的是想以实例属性的方法去访问每个对象
Girl.list_girl.append(self)
a1=Girl('阿珂',100,23,166)
a2=Girl('苏荃',92,32,154)
a3=Girl('双儿',90,25,178)
a4=Girl('小郡主',76,22,168)
a5=Girl('方怡',75,27,165)
a6=Girl('建宁',86,25,175)
a7=Girl('曾柔',67,24,163)
# 需求:查找所有高于160的
def fun01():
for item in Girl.list_girl:
if item.height > 160:
yield item
# 需求:颜值大于90的
def fun02():
for item in Girl.list_girl:
if item.outlook > 90:
yield item
for data in fun01():
print(data.name)
for data in fun02():
print(data.name)
'''
封装 找不同点
继承 找相同点
多态 实现不同的目的
'''
def condition03(item):
return item.height > 160
def condition04(item):
return item.outlook > 90
def find01(func):
for item in Girl.list_girl:
if func(item):
yield item
for girl in find01(condition03):
print(girl.name,end='\t')
print('\n')
for girl in find01(condition04):
print(girl.name)
'''
高阶函数
'''
class Girl:
list_girl = []# 类属性 存放所有美女信息
def __init__(self,name,outlook,age,height):
self.name = name
self.outlook = outlook
self.age = age
self.height = height
# print(self)
#将实例对象存入列表中,目的是想以实例属性的方法去访问每个对象
Girl.list_girl.append(self)
def __str__(self):
return f'{self.name}-{self.age}-{self.outlook}-{self.height}'
a01=Girl('阿珂',100,23,166)
a02=Girl('苏荃',92,32,154)
a03=Girl('双儿',90,25,178)
a04=Girl('小郡主',76,22,168)
a05=Girl('方怡',75,27,165)
a06=Girl('建宁',86,25,175)
a07=Girl('曾柔',67,24,163)
print(a01)
print('------')
#1. 打印所有对象的名称
for element in map(lambda item:item.name,Girl.list_girl):
print(element)
print('-------')
#2. 获取所有颜值大于80的对象
for nice in filter(lambda item:item.outlook>80,Girl.list_girl):
print(nice)
print('-------')
#3. 获取年龄最大的美女对象 (max返回最大值的对象)
print(max(Girl.list_girl,key=lambda item:item.age))
print('-------')
#4. 按颜值升序
for line in sorted(Girl.list_girl,key=lambda item:item.outlook):#reverse=True是降序,默认是False升序
print(line)
2.函数作为返回值
2.1闭包
闭包是指引用了此函数外部嵌套函数的变量的函数 闭包就是能够读取其他函数内部变量的函数。只有函数内部的嵌套函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数,同时这个函数又引用了外部的变量。
条件:
- 必须有一个内嵌函数 。
- 内嵌函数必须引用外部函数中变量
- 外部函数返回值必须是内嵌函数。
2.2装饰器
装饰器是一个函数,主要作用是来用包装另一个函数或类。在不修改被装饰的函数的源代码,不改变被装饰的函数的调用方式的情况下添加或改变原函数的功能。
'''
语法
'''
def 装饰器函数名(fn):
语句块
return 函数对象
@装饰器函数名 <换行>
def 被装饰函数名(形参列表):
语句块
当使用@mydeco
语法装饰myfun
函数时,实际上发生的是:
myfun
函数作为参数传递给了mydeco
装饰器。- 在
mydeco
内部,首先调用了fn()
,即此时调用了myfun
函数,产生了输出:“函数myfun被调用”。 - 接着,打印了"装饰器函数被调用了,并返回了fx"。
- 然后,
mydeco
装饰器返回了新的函数fx
。
因此,此刻myfun
实际上被替换成了新的函数fx
。这样的行为正是Python装饰器的特性之一:装饰器可以修改函数的行为,甚至完全替换被装饰的函数。
2.2.1基本装饰器
有参数的函数装饰器(在myfunc外加了一层)
def mydeco(fn):
fn()
print("装饰器函数被调用了,并返回了fx")
def fx():
print("fx被调用了")
# return fn()
return fx
@ mydeco
def myfun():
print("函数myfun被调用")
myfun()
myfun()
2.2.2带参数的装饰器
def repeat(num):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3) # 应用装饰器,重复执行下面的函数3次
def greet(name):
print(f"Hello, {name}!")
greet("Alice") # 调用被装饰的函数
repeat
是一个接受参数的装饰器工厂函数,它返回一个装饰器。decorator
是真正的装饰器,它接受一个函数func
作为参数。wrapper
函数重复执行被装饰的函数num
次。- 使用
@repeat(3)
应用装饰器,使greet
函数被执行3次。
注意:带参数的装饰器需要三层函数,def wrapper(args, kwargs) 传入的是被修饰的函数的参数。
2.2.3装饰器链
def uppercase(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
def exclamation(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + "!"
return wrapper
@exclamation
@uppercase
def say_hello(name):
return f"Hello, {name}"
greeting = say_hello("Bob")
print(greeting) # 输出 "HELLO, BOB!"
具体的执行过程如下:
- 装饰器是从内到外依次应用的。在你的代码中,首先应用的是
@uppercase
,然后是@exclamation
。 @uppercase
装饰器会先包裹say_hello
函数,然后@exclamation
装饰器再包裹已经被@uppercase
包裹过的函数。
步骤详细如下:
- 首先
@uppercase
包装say_hello
函数:- 调用
say_hello("Bob")
返回"Hello, Bob"
。 @uppercase
装饰器的wrapper
函数将结果转换为大写,变为"HELLO, BOB"
。
- 调用
- 然后
@exclamation
包装已经被@uppercase
包装过的say_hello
函数:- 调用
wrapper
(即@uppercase
装饰器的wrapper
函数)返回"HELLO, BOB"
。 @exclamation
装饰器的wrapper
函数将结果加上一个感叹号,变为"HELLO, BOB!"
。
- 调用
2.2.4 类装饰器
class MyDecorator:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
print("Something is happening before the function is called.")
result = self.func(*args, **kwargs)
print("Something is happening after the function is called.")
return result
@MyDecorator # 应用类装饰器
def say_hello(name):
print(f"Hello, {name}!")
say_hello("Charlie") # 调用被装饰的函数
-
MyDecorator
是一个类装饰器,它接受一个函数func
作为参数并在__call__
方法中执行额外操作。 -
使用
@MyDecorator
应用类装饰器,它将包装say_hello
方法,使其在调用前后执行额外操作。 -
与基本装饰器类似