python基础之函数式编程
一、定义:
函数作为参数作用:将核心逻辑传入方法体,使该方法的适用性更广,体现了面向对象的开闭原则;
函数作为返回值作用:逻辑连续,当内部函数被调用时,不脱离当前的逻辑。
二、高阶函数:
1、定义:将函数作为参数或返回值的函数。
2、常见内置高阶函数:
三、lambda表达式:
四、闭包:
五、函数装饰器(decorators):
六、基础代码:
代码1:
""" 函数式编程 -- 方法作为参数 """ def fun01(): print("fun01执行喽") # 调用fun01,将返回值赋值给变量a # a = fun01() # 将函数值赋值给变量a(没有执行fun01) a = fun01 # 调用变量a,间接执行函数fun01 a() # 将方法fun01作为方法的参数func进行传递 def fun02(func): print("fun02执行喽") # 对于fun02的定义者而言,不知道也不需要知道func的具体逻辑. func() fun02(fun01) list01 = [1,2,33,4,45,6] # def find_demo01(target): # for item in target: # if item> 5: # yield item # # def find_demo02(target): # for item in target: # if item % 2 != 0: # yield item # # def find_demo03(target): # for item in target: # if item < 3: # yield item # -------------------------------------------- # 相同点: def find_demo(target,func): for item in target: # 本行代码,又将不变的与变化的紧密相连 # if condition01(item): # 本行代码,使用形参func将不变的与变化的隔离开. if func(item): yield item # -------------------------------------------- # 提取不同点: def condition01(item): return item> 5 def condition02(item): return item % 2 != 0 def condition03(item): return item < 3 for item in find_demo(list01,condition03): print(item)
代码2:
""" lambda 表达式(匿名方法) 语法: lambda 参数:方法体 练习: exercise05.py """ def fun01(): print("我是普通方法") fun01() def fun02(a): print("我是普通方法,参数是,", a) fun02(500) def fun03(): return True print(fun03()) # ------------------------- a01 = lambda: print("我是lambda方法") a01() a02 = lambda a: print("我是lambda方法,参数是,", a) a02(500) a03 = lambda: True print(a03()) #------------------------------------ from common.custom_list_tools import ListHelper list01 = [1,2,33,4,45,6] for item in ListHelper.find_all(list01,lambda item:item > 5): print(item) for item in ListHelper.find_all(list01,lambda item:item % 2 != 0): print(item) # 提取不同点: # def condition01(item): # return item> 5 # # def condition02(item): # return item % 2 != 0 # # def condition03(item): # return item < 3 # for item in ListHelper.find_all(list01,condition01): # print(item)
代码3:
""" 高阶函数 """ from day16.common.custom_list_tools import ListHelper # 敌人类(编号/姓名/攻击力/血量/攻击速度...) class Enemy: def __init__(self, id, name, hp, atk, atk_speed): self.id = id self.name = name self.hp = hp self.atk = atk self.atk_speed = atk_speed list01 = [ Enemy(101, "玄冥大老", 200, 800, 5), Enemy(102, "玄冥小老", 150, 700, 3), Enemy(103, "qtx", 800, 1000, 50), Enemy(104, "吕泽玛利亚", 0, 300, 2), Enemy(105, "赵金多", 500, 900, 10), ] # 1. filter 过滤,类似于ListHelper.find_all. # 过滤出编号大于102的敌人 # for item in filter(lambda e: e.id > 102, list01): # print(item.id) # # for item in ListHelper.find_all(list01, lambda e: e.id > 102): # print(item.id) # 2. map 映射,类似于ListHelper.select # 映射出所有敌人的姓名 for item in map(lambda e:e.name,list01): print(item) for item in ListHelper.select(list01,lambda e:e.name): print(item) # # 按照血量升序排列,类似于ListHelper.order_by # for item in sorted(list01,key = lambda e:e.hp ): # print(item.hp) # # # 按照血量降叙排列 # for item in sorted(list01,key = lambda e:e.hp,reverse=True): # print(item.hp) # ListHelper.order_by(list01,lambda e:e.hp) # for item in list01: # print(item.hp) # 获取攻击力最大的敌人 result = max(list01,key = lambda e:e.atk) print(result.name) result = ListHelper.get_max(list01,lambda e:e.atk) print(result.name)
代码4:
""" Encolsing 外部嵌套作用域 """ # 全局变量G g01 = 100 def fun01(): # fun01局部变量L # E外部嵌套作用域 a = 1 def fun02(): b = 2 # fun02局部变量L # print("fun02:", a) # 可以访问外部嵌套变量a # a = 2222 # 没有修改外部嵌套变量a,而是创建了新的局部变量a # print("fun02:",a) nonlocal a # 声明外部嵌套变量a a = 2222 print("fun02:",a) fun02() print("fun01:",a) fun01()
代码5:
""" 闭包 """ def fun01(): print("fun01执行喽") a = 1 def fun02(): print("fun02执行喽") print("外部变量是:",a) return fun02 # 得到的是内部函数 result = fun01() # 调用内部函数,因为内部函数使用了外部变量,所以称之为闭包. result()# 可以使用外部变量,说明外部函数在调用后没有释放. # 案例: def give_gift_money(money): """ 获取压岁钱 """ print("得到了%d压岁钱"%money) def child_buy(target,price): """ 孩子需要买东西 """ nonlocal money if money >= price: money -= price print("孩子花了%d钱,买了%s,还剩下%d钱."%(price,target,money)) else: print("压岁钱不够了") return child_buy action = give_gift_money(10000) action("98k",3500) action("小猪佩奇",300) action("大黄蜂",8000) # 体会:闭包使得逻辑连续(因为内部函数可以使用外部变量).
代码6:
""" 装饰器 -- 闭包的应用 """ # def say_hello(): # print("hello") # # # def say_goodbye(): # print("goodbye") # # # say_hello() # say_goodbye() # 需求:在两个方法实现的功能基础上,增加新功能(打印方法名称) # def say_hello(): # print(say_hello.__name__) # print("hello") # # # def say_goodbye(): # print(say_goodbye.__name__) # print("goodbye") # # # say_hello() # say_goodbye() # 缺点:代码重复. # 解决:提取打印方法名称的功能 # def print_func_name(func): # print(func.__name__) # # def say_hello(): # # print(say_hello.__name__) # print_func_name(say_hello) # print("hello") # # # def say_goodbye(): # # print(say_goodbye.__name__) # print_func_name(say_goodbye) # print("goodbye") # say_hello() # say_goodbye() # 缺点:在两个已有功能的内部,增加新功能,代码可读性差. # def say_hello(): # # print_func_name(say_hello) # print("hello") # def say_goodbye(): # # print_func_name(say_goodbye) # print("goodbye") # # def print_func_name(func): # # 包装新旧功能 # def wrapper(): # # 增加的新功能 # print(func.__name__) # # 旧功能 # func() # # return wrapper # 返回包装器 # # say_hello = print_func_name(say_hello) # say_goodbye = print_func_name(say_goodbye) # # say_hello() # say_goodbye() # 缺点:调用者完成包装新旧方法的任务. # 解决:应该有定义者完成. # def print_func_name(func): # # 包装新旧功能 # def wrapper(): # # 增加的新功能 # print(func.__name__) # # 旧功能 # func() # # return wrapper # 返回包装器 # # @print_func_name # say_hello = print_func_name(say_hello) # def say_hello(): # print("hello") # return "哈哈" # # @print_func_name # def say_goodbye(): # print("goodbye") # # #---------以上是定义者--以下是调用者----------------- # say_hello() # say_goodbye() # 缺点:旧功能的返回值不能被客户端代码接受到. # 旧功能的参数,客户端代码也无法传入. # def print_func_name(func): # # 包装新旧功能 # def wrapper(name): # # 增加的新功能 # print(func.__name__) # # 旧功能 # return func(name) # # return wrapper # 返回包装器 # 缺点:包装器不能适应所有的旧功能参数 def print_func_name(func): # 包装新旧功能 def wrapper(*args,**kwargs): # 增加的新功能 print(func.__name__) # 旧功能 return func(*args,**kwargs) return wrapper # 返回包装器 @print_func_name # say_hello = print_func_name(say_hello) def say_hello(name): print(name,"hello") return "哈哈" @print_func_name def say_goodbye(name,age): print(age,name,"goodbye") #---------以上是定义者--以下是调用者----------------- print(say_hello("张无忌")) say_goodbye("赵敏",25)
代码7:
""" 练习:使用装饰器实现: 为两个已有功能(进入后台,删除订单),增加新功能(验证权限). """ # 1. 定义装饰器(新功能 + 旧功能) def verify_permissions(func): def wrapper(*args, **kwargs): print("验证权限") return func(*args, **kwargs) return wrapper # 2. 拦截调用 @verify_permissions def enter_background(loginId,pwd): print(loginId,pwd) print("进入后台系统.....") @verify_permissions def delete_order(order_id): print("删除%d订单..."%order_id) enter_background("zs",123) delete_order(101)
代码8:
""" 练习2:为两个已有功能(存款取款),添加新功能(验证账户) """ def verify_accont(func): def wrapper(*args,**kwargs): print("验证账户") return func(*args,**kwargs) return wrapper #deposit = verify_accont(deposit) @verify_accont def deposit(money): print("存款:",money) @verify_accont def withdraw(): print("取钱") return 10000 deposit(5000) print(withdraw())
代码9:
""" 练习: 为学生的学习方法,添加新功能(打印执行时间) """ import time def print_execute_time(func): def wrapper(*args, **kwargs): # 记录执行前的时间 start_time = time.time() result = func(*args, **kwargs) # 统计执行时间 execute_time = time.time() - start_time print("执行时间是:", execute_time) return result return wrapper class Student: def __init__(self, name): self.name = name @print_execute_time def study(self): print("开始学习喽") time.sleep(2) # 睡眠两秒 模拟学习了两秒 s01 = Student("无忌") s01.study()