Python 高级
第五章 函数式编程
- 定义:用一系列函数解决问题。
- 函数可以赋值给变量,赋值后变量绑定函数。
- 允许将函数作为参数传入另一个函数。
- 允许函数返回一个函数。
- 高阶函数:将函数作为参数或返回值的函数。
一、函数作为参数
- 将核心逻辑传入方法体,使该方法的适用性更广,体现了面向对象的开闭原则。
"""
函数式编程 - 语法
"""
def func01():
print("func01执行")
a = func01
a()
def func02():
print("func02执行")
def func03(func):
print("func03执行")
func()
func03(func02)
func03(func01)
"""
函数式编程 - 思想
"""
list01 = [4, 54, 56, 65, 67, 7]
def find01():
for item in list01:
if item > 50:
yield item
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 func(item):
yield item
for item in find(condition01):
print(item)
for item in find(condition02):
print(item)
"""
练习1:在老婆列表中,查找颜值大于90的所有老婆
练习2:在老婆列表中,查找身高小于170的所有老婆
"""
class Wife:
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
list_wife = [
Wife("双儿", 96, 22, 166),
Wife("阿珂", 100, 23, 173),
Wife("小郡主", 96, 22, 161),
Wife("方怡", 86, 27, 166),
Wife("苏荃", 99, 31, 176),
Wife("建宁", 93, 24, 163),
Wife("曾柔", 88, 26, 170),
]
def find01():
for item in list_wife:
if item.face_score > 90:
yield item
def find02():
for item in list_wife:
if item.height < 170:
yield item
def condition01(item):
return item.face_score > 90
def condition02(item):
return item.height < 170
def find(func):
for item in list_wife:
if func(item):
yield item
for item in find(condition01):
print(item)
for item in find(condition02):
print(item)
"""
可迭代对象工具模块
"""
class IterableHelper:
@staticmethod
def find_all(iterable, func_condition):
"""
在可迭代对象中查找满足条件的所有元素
:param iterable: 可迭代对象类型,需要查找的数据
:param func_condition:函数类型,查找的条件
:return:生成器对象
"""
for item in iterable:
if func_condition(item):
yield item
@staticmethod
def first(iterable, func_condition):
"""
在可迭代对象中查找第一个满足条件的元素
:param iterable:可迭代对象类型,需要查找的数据
:param func_condition:函数类型,查找的条件
:return:第一个满足条件的元素
"""
for item in iterable:
if func_condition(item):
return item
@staticmethod
def get_count(iterable, func_condition):
"""
在可迭代对象中,获取满足条件的元素数量
:param iterable:可迭代对象类型,需要查找的数据
:param func_condition:函数类型,查找的条件
:return:int类型,数量
"""
count = 0
for item in iterable:
if func_condition(item):
count += 1
return count
@staticmethod
def select(iterable, func_handle):
"""
通用的筛选方法
:param iterable:可迭代对象类型,需要筛选的数据
:param func_handle:筛选的逻辑
:return:生成器对象
"""
for item in iterable:
yield func_handle(item)
@staticmethod
def is_exists(iterable, func_condition):
"""
判断可迭代对象中是否存在某个条件的对象
:param iterable:可迭代对象类型,需要筛选的数据
:param func_condition:查找的条件
:return:bool,True表示存在,False表示不存在
"""
for item in iterable:
if func_condition(item):
return True
return False
@staticmethod
def sum(iterable, func_handle):
"""
根据指定逻辑累加可迭代对象中的元素
:param iterable:可迭代对象类型,需要累加的数据
:param func_handle:累加逻辑
:return:数值类型,累加结果
"""
sum_value = 0
for item in iterable:
sum_value += func_handle(item)
return sum_value
@staticmethod
def get_max(iterable, func_condition):
"""
根据条件在可迭代对象中获取最大元素
:param iterable:可迭代对象类型,需要查找的数据
:param func_condition:指定条件
:return:最大元素
"""
max_value = iterable[0]
for i in range(1, len(iterable)):
if func_condition(max_value) < func_condition(iterable[i]):
max_value = iterable[i]
return max_value
@staticmethod
def delete_all(iterable, func_condition):
"""
根据条件删除多个元素
:param iterable: 可迭代对象类型,需要删除的数据
:param func_condition:删除条件
:return:删除的元素数量
"""
count = 0
for i in range(len(iterable) - 1, -1, -1):
if func_condition(iterable[i]):
del iterable[i]
count += 1
return count
@staticmethod
def order_by(iterable, func_condition):
"""
根据条件升序排列
:param iterable:可迭代对象类型,需要排序的数据
:param func_condition:比较条件
"""
for r in range(len(iterable) - 1):
for c in range(r + 1, len(iterable)):
if func_condition(iterable[r]) > func_condition(iterable[c]):
iterable[r], iterable[c] = iterable[c], iterable[r]
"""
需求1:
1. 在老婆列表中查找方怡对象
2. 在老婆列表中查找颜值大于95的单个老婆对象
first
需求2:
1. 计算老婆列表中姓名大于2个字的老婆数量
2. 计算老婆列表年龄小于25的老婆数量
get_count
需求3:
1. 获取老婆列表中所有老婆的姓名
2. 获取老婆列表中所有老婆的姓名与颜值
select
需求4:
1. 在老婆列表中判断是否存在姓名是苏荃的元素
2. 在老婆列表中判断是否存在高度大于170的元素
is_exists
需求5:
1. 累加老婆列表中所有人的年龄
2. 累加老婆列表中所有人的高度
sum
需求7:
1. 在老婆列表中找出颜值最高的老婆对象
2. 在老婆列表中找出年龄最大的老婆对象
get_max
需求8:
1. 在老婆列表中删除年龄小于25的所有老婆
2. 在老婆列表中删除身高大于170的所有老婆
delete_all
需求9:
1. 对老婆列表根据年龄进行升序排列
2. 对老婆列表根据颜值进行升序排列
order_by
步骤:
1. 根据需求,定义函数.
2. 将变化点单独定义为函数.
3. 将通用代码定义位函数(使用参数隔离变化点)
4. 在IterableHelper类中添加新功能
5. 在当前模块中进行测试
"""
from common.iterable_tools import IterableHelper
class Wife:
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_wife = [
Wife("双儿", 96, 22, 166),
Wife("阿珂", 100, 23, 173),
Wife("小郡主", 96, 22, 161),
Wife("方怡", 86, 27, 166),
Wife("苏荃", 99, 31, 176),
Wife("建宁", 93, 24, 163),
Wife("曾柔", 88, 26, 170),
]
for item in IterableHelper.find_all(list_wife,lambda item:item.face_score > 90):
print(item)
print(IterableHelper.first(list_wife,lambda item:item.face_score > 95))
print(IterableHelper.get_count(list_wife,lambda item: item.age < 25))
def handle01(item):
return item.name
def handle02(item):
return (item.name,item.face_score)
for item in IterableHelper.select(list_wife,handle02):
print(item)
print(IterableHelper.is_exists(list_wife,lambda item:item.height > 170))
print(IterableHelper.sum(list_wife,lambda item:item.height))
print(IterableHelper.get_max(list_wife,lambda element:element.height))
IterableHelper.order_by(list_wife,lambda e:e.age)
for item in list_wife:
print(item)
1. lambda 表达式
- 定义:是一种匿名方法。
- 作用:作为参数传递时语法简洁,优雅,代码可读性强。
随时创建和销毁,减少程序耦合度。
- 语法
变量 = lambda 形参: 方法体
变量(实参)
- 说明:
– 形参没有可以不填
– 方法体只能有一条语句,且不支持赋值语句。
"""
lambda表达式
匿名方法
语法:
lambda 参数:方法体
"""
func01 = lambda a,b:a > b
print(func01(10,20))
func02 = lambda :"ok"
print(func02())
func03 = lambda :print("ok")
func03()
func03 = lambda a:print(a)
func03(100)
2. 内置高阶函数
- map(函数,可迭代对象):使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。
- filter(函数,可迭代对象):根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
- sorted(可迭代对象,key = 函数,reverse = bool值):排序,返回值为排序结果。
- max(可迭代对象,key = 函数):根据函数获取可迭代对象的最大值。
- min(可迭代对象,key = 函数):根据函数获取可迭代对象的最小值。
"""
内置高阶函数
这个函数的参数或者返回值是函数
练习:exercise02
"""
class Wife:
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_wife = [
Wife("双儿", 96, 22, 166),
Wife("阿珂", 100, 23, 173),
Wife("小郡主", 96, 22, 161),
Wife("方怡", 86, 27, 166),
Wife("苏荃", 99, 31, 176),
Wife("建宁", 93, 24, 163),
Wife("曾柔", 88, 26, 170),
]
for element in map(lambda item: item.name, list_wife):
print(element)
for element in filter(lambda item: item.face_score > 90, list_wife):
print(element)
print(max(list_wife,key = lambda item:item.face_score))
print(min(list_wife,key = lambda item:item.face_score))
for item in sorted(list_wife,key = lambda item:item.height):
print(item)
for item in sorted(list_wife,key = lambda item:item.height,reverse=True):
print(item)
二、函数作为返回值
"""
外部嵌套作用域
"""
def func01():
a = 10
def func02():
nonlocal a
a = 20
func02()
print(a)
func01()
1. 闭包
1.1 三要素
- 必须有一个内嵌函数。
- 内嵌函数必须引用外部函数中变量。
- 外部函数返回值必须是内嵌函数。
1.2 语法
def 外部函数名(参数):
外部变量
def 内部函数名(参数):
使用外部变量
return 内部函数名
变量 = 外部函数名(参数)
变量(参数)
1.3 定义
- 在一个函数内部的函数,同时内部函数又引用了外部函数的变量。
1.4 本质
- 闭包是将内部函数和外部函数的执行环境绑定在一起的对象。
1.5 优点
1.6 缺点
- 外部变量一直存在于内存中,不会在调用结束后释放,占用内存。
1.7 作用
"""
闭包
三大要素:
具有内外函数
内部函数访问外部函数变量
外部函数返回内部函数
字面意思:封闭程序运行环境 --> 保存
体现:
外部函数执行过后,栈帧不释放,等待内部函数使用.
"""
def func01():
a = 100
def func02():
print(a)
return func02
result = func01()
result()
"""
闭包应用
逻辑连续
装饰器
"""
def give_gife_money(money):
print("得到了", money, "元压岁钱")
def child_buy(target, price):
nonlocal money
money -= price
print("购买了", target, "还剩", money, "元")
return child_buy
action = give_gife_money(500)
action("变形金刚", 130)
action("遥控飞机", 250)
action("零食", 120)
2. 装饰器 decorator
2.1 定义
- 在不改变原函数的调用以及内部代码情况下,为其添加新功能的函数。
2.2 语法
def 函数装饰器名称(func):
def 内嵌函数(*args, **kwargs):
需要添加的新功能
return func(*args, **kwargs)
return内嵌函数
原函数 = 内嵌函数
@ 函数装饰器名称
def 原函数名称(参数):
函数体
原函数(参数)
2.3 本质
- 使用“@函数装饰器名称”修饰原函数,等同于创建与原函数名称相同的变量,关联内嵌函数;故调用原函数时执行内嵌函数。
- 原函数名称 = 函数装饰器名称(原函数名称)
2.4 装饰器链
- 一个函数可以被多个装饰器修饰,执行顺序为从近到远。
"""
装饰器
"""
def func01():
print("func01执行喽")
return "ok"
def func02(a):
print(a, "func02执行喽")
def print_func_name(func):
def wrapper(*args, **kwargs):
print(func.__name__)
return func(*args, **kwargs)
return wrapper
func01 = print_func_name(func01)
print(func01())
"""
装饰器
"""
def print_func_name(func):
def wrapper(*args, **kwargs):
print(func.__name__)
return func(*args, **kwargs)
return wrapper
@print_func_name
def func01():
print("func01执行喽")
return "ok"
@print_func_name
def func02(a):
print(a, "func02执行喽")
print(func01())
func02(100)
"""
在不改变原有功能的定义与调用情况下(进入后台、删除订单),
为其增加新功能(验证权限).
"""
def verify_permissions(func):
def wrapper(*args, **kwargs):
print("验证权限")
return func(*args, **kwargs)
return wrapper
@verify_permissions
def enter_background():
print("进入后台")
@verify_permissions
def delete_order():
print("删除订单")
enter_background()
delete_order()
"""
在不改变原有功能的定义与调用情况下,为其增加新功能.
"""
import time
def print_execute_time(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
stop_time = time.time()
print(stop_time - start_time)
return result
return wrapper
@print_execute_time
def func01():
sum_value = 0
for i in range(100):
sum_value += i
return sum_value
@print_execute_time
def func02(n):
sum_value = 0
for i in range(n):
sum_value += i
return sum_value
func01()
func02(100000)