5 函数式编程
(1) 定义:用一系列函数解决问题。
-- 函数可以赋值给变量,赋值后变量绑定函数。
-- 允许将函数作为参数传入另一个函数。
-- 允许函数返回一个函数。
(2) 高阶函数:将函数作为参数或返回值的函数。
5.1 函数作为参数
将核心逻辑传入方法体,使该方法的适用性更广,体现
了面向对象的开闭原则。
list01 = [ 342 , 4 , 54 , 56 , 6776 ]
def get_number_gt_100 ( ) :
for number in list01:
if number > 100 :
yield number
def get_number_by_even ( ) :
for number in list01:
if number % 2 == 0 :
yield number
def condition01 ( number) :
return number > 100
def condition02 ( number) :
return number % 2 == 0
def find_all ( condition) :
for item in list01:
if condition( item) :
yield item
def condition03 ( number) :
return number < 10
for item in find_all( condition03) :
print ( item)
练习1:
需求:
定义函数,在列表中查找奇数
定义函数,在列表中查找能被3或5整除的数字
步骤:
-- 根据需求,写出函数。
-- 因为主体逻辑相同,核心算法不同.
所以使用函数式编程思想(分、隔、做)
创建通用函数find_all
-- 在当前模块中调用
练习2:
需求:
定义函数,在员工列表中查找编号是1003的员工
定义函数,在员工列表中查找姓名是孙悟空的员工
步骤:
-- 根据需求,写出函数。
-- 因为主体逻辑相同,核心算法不同.
所以使用函数式编程思想(分、隔、做)
创建通用函数find_single
-- 在当前模块中调用
class Employee :
def __init__ ( self, eid, did, name, money) :
self. eid = eid
self. did = did
self. name = name
self. money = money
list_employees = [
Employee( 1001 , 9002 , "师父" , 60000 ) ,
Employee( 1002 , 9001 , "孙悟空" , 50000 ) ,
Employee( 1003 , 9002 , "猪八戒" , 20000 ) ,
Employee( 1004 , 9001 , "沙僧" , 30000 ) ,
Employee( 1005 , 9001 , "小白龙" , 15000 ) ,
]
5.1.1 lambda 表达式
(1) 定义:是一种匿名方法
(2) 作用:
-- 作为参数传递时语法简洁,优雅,代码可读性强。
-- 随时创建和销毁,减少程序耦合度。
(3) 语法
变量 = lambda 形参: 方法体
变量( 实参)
(4) 说明:
-- 形参没有可以不填
-- 方法体只能有一条语句,且不支持赋值语句。
(5) 演示:
from common. iterable_tools import IterableHelper
list01 = [ 342 , 4 , 54 , 56 , 6776 ]
for item in IterableHelper. find_all( list01, lambda number: number > 100 ) :
print ( item)
for item in IterableHelper. find_all( list01, lambda number: number % 2 == 0 ) :
print ( item)
5.1.2 内置高阶函数
(1) map(函数,可迭代对象):使用可迭代对象中
的每个元素调用函数,将返回值作为新可迭代对象元
素;返回值为新可迭代对象。
(2) filter(函数,可迭代对象):根据条件筛选可
迭代对象中的元素,返回值为新可迭代对象。
(3) sorted(可迭代对象,key = 函数,
reverse = bool值):排序,返回值为排序结果。
(4) max(可迭代对象,key = 函数):根据函数获取
可迭代对象的最大值。
(5) min(可迭代对象,key = 函数):根据函数获取
可迭代对象的最小值。
(6) 演示:
class Employee :
def __init__ ( self, eid, did, name, money) :
self. eid = eid
self. did = did
self. name = name
self. money = money
list_employees = [
Employee( 1001 , 9002 , "师父" , 60000 ) ,
Employee( 1002 , 9001 , "孙悟空" , 50000 ) ,
Employee( 1003 , 9002 , "猪八戒" , 20000 ) ,
Employee( 1004 , 9001 , "沙僧" , 30000 ) ,
Employee( 1005 , 9001 , "小白龙" , 15000 ) ,
]
for item in map ( lambda item: item. name, list_employees) :
print ( item)
for item in filter ( lambda item: item. did == 9002 , list_employees) :
print ( item. __dict__)
emp = max ( list_employees, key= lambda emp: emp. money)
print ( emp. __dict__)
new_list = sorted ( list_employees, key= lambda emp: emp. money)
print ( new_list)
new_list = sorted ( list_employees, key= lambda emp: emp. money, reverse= True )
print ( new_list)
练习:
-- 在商品列表,获取所有名称与单价
-- 在商品列表中,获取所有单价小于10000的商品
-- 对商品列表,根据单价进行降序排列
-- 获取元组中长度最大的列表 ([1,1],[2,2,2],
[3,3,3])
class Commodity :
def __init__ ( self, cid= 0 , name= "" , price= 0 ) :
self. cid = cid
self. name = name
self. price = price
list_commodity_infos = [
Commodity( 1001 , "屠龙刀" , 10000 ) ,
Commodity( 1002 , "倚天剑" , 10000 ) ,
Commodity( 1003 , "金箍棒" , 52100 ) ,
Commodity( 1004 , "口罩" , 20 ) ,
Commodity( 1005 , "酒精" , 30 ) ,
]
5.2 函数作为返回值
逻辑连续,当内部函数被调用时,不脱离当前的逻辑。
5.2.1 闭包
(1) 三要素:
-- 必须有一个内嵌函数。
-- 内嵌函数必须引用外部函数中变量。
-- 外部函数返回值必须是内嵌函数。
(2) 语法
def 外部函数名( 参数) :
外部变量
def 内部函数名( 参数) :
使用外部变量
return 内部函数名
变量 = 外部函数名( 参数)
变量( 参数)
(3) 定义:是由函数及其相关的引用环境组合而成
的实体。
(4) 优点:内部函数可以使用外部变量。
(5) 缺点:外部变量一直存在于内存中,不会在调用
结束后释放,占用内存。
(6) 作用:实现python装饰器。
(7) 演示:
def give_gife_money ( money) :
print ( "获得" , money, "元压岁钱" )
def child_buy ( commodity, price) :
nonlocal money
money -= price
print ( "购买了" , commodity, "花了" , price, "元,还剩下" , money)
return child_buy
action = give_gife_money( 500 )
action( "变形金刚" , 200 )
action( "芭比娃娃" , 300 )
练习:使用闭包模拟以下情景:
在银行开户存入10000
购买xx商品花了xx元
购买xx商品花了xx元
5.2.2 函数装饰器decorator
(1) 定义:在不改变原函数的调用以及内部代码情况
下,为其添加新功能的函数。
(2) 语法
def 函数装饰器名称( func) :
def wrapper ( * args, ** kwargs) :
需要添加的新功能
return func( * args, ** kwargs)
return wrapper
@ 函数装饰器名称
def 原函数名称( 参数) :
函数体
原函数( 参数)
(3) 本质:使用“@函数装饰器名称”修饰原函数,
等同于创建与原函数名称相同的变量,关联内嵌函数;
故调用原函数时执行内嵌函数。
原函数名称 = 函数装饰器名称(原函数名称)
def func01 ( ) :
print ( "旧功能" )
def new_func ( func) :
def wrapper ( ) :
print ( "新功能" )
func( )
return wrapper
func01 = new_func( func01)
func01( )
func01( )
(3) 装饰器链:
一个函数可以被多个装饰器修饰,执行顺序为
从近到远。
练习1:不改变插入函数与删除函数代码,为其增加
验证权限的功能
def verify_permissions ( ) :
print ( "验证权限" )
def insert ( ) :
print ( "插入" )
def delete ( ) :
print ( "删除" )
insert( )
delete( )
练习2:为sum_data,增加打印函数执行时间的功能.
函数执行时间公式: 执行后时间 - 执行前时间
def sum_data ( n) :
sum_value = 0
for number in range ( n) :
sum_value += number
return sum_value
print ( sum_data( 10 ) )
print ( sum_data( 1000000 ) )