【python核心】函数式编程(一)
文章目录
- 函数式编程
-
- 语法
- 思想
- 练习
- 函数式编程(函数作为参数)
- lambda表达式
-
- 知识点
- 练习
- 内置高阶函数
-
- 练习
- 外部嵌套作用域
- 总结
函数式编程
定义:用一系列函数解决问题。
- 函数可以赋值给变量,赋值后变量绑定函数。
- 允许将函数作为参数传入另一个函数。
- 允许函数返回一个函数。
高阶函数:将函数作为参数或返回值的函数。
语法
""" 函数式编程 语法"""def fun01(): print("fun01执行喽")#调用方法,执行方法体re1 = fun01()print(re1)#将函数赋值给变量re2 = fun01#通过变量,调用函数re2()def fun02(): print("fun02执行喽")#将函数作为函数的参数进行传递#好处:将一个函数的代码(fun02/fun01),注入到另外一个函数中(fun03)。def fun03(func): print("fun03执行喽") func()fun03(fun01)fun03(fun02)
思想
""" 函数式编程 思想"""class SkillData: def __init__(self,id,name,atk_ratio,duration): """ 技能信息 :param id:技能编号 :param name:技能名称 :param atk_ratio: 攻击比例 :param duration: 持续时间 """ self.id = id self.name = name self.atk_ratio = atk_ratio self.duraftion = duration def __str__(self): return "技能数据是:%d,%s,%d,%d"%(self.id,self.name,self.atk_ratio,self.duraftion)list_skill = [ SkillData(101, "乾坤大挪移",5, 10), SkillData(102, "降龙十八掌", 8, 5), SkillData(103, "葵花宝典",10,2),]def find01(): for item in list_skill: if item.atk_ratio > 6 : yield itemdef find02(): for item in list_skill: if 4 < item.duraftion < 11: yield itemdef find04(): for item in list_skill: if len(item.name)> 4 and item.duraftion <6 : yield item#"封装"(分而治之,变而疏之)#将每个变化的条件,单独定义在函数中。def condition01(item): return item.atk_ratio > 6def condition02(item): return 4 < item.duraftion < 11def condition03(item): return len(item.name)> 4 and item.duraftion <6#"继承"(隔离变化)def find(func_condition): """ 通用的查找方法 :param func_condition:查找条件,函数类型函数名(变量)--》返回值bool类型 """ for item in list_skill: #"多态":调用父(变量),执行子(具体函数) if func_condition(item): yield itemfor item in find(condition01): print(item)for item in find(condition02): print(item)for item in find(condition03): print(item)
练习
练习1:
list01 = [ 43,4,5,5,6,7,87]
需求1:在列表中查找所有偶数。
需求2:在列表中查找所有大于10的数。
需求3:在列表中查找所有范围在10–50之间的数。
1.使用生成器函数实现以上3个需求。
2.体会函数式编程的“封装“。
将三个函数变化点提取到另外三个函数中,将共性提取到另外一个函数中。
3.体会函数式编程的"继承"与“多态"。
使用变量隔离变化点,在共性函数中调用变量。
4.测试(执行上述功能)。
list01 = [43,4,5,5,6,7,87]# def find01():# for item in list01:# if item % 2 == 0:# yield item## for item in find01():# print(item)## def find02():# for item in list01:# if item > 10:# yield item## for item in find02():# print(item)## def find03():# for item in list01:# if 10 < item < 50 :# yield item## for item in find03():# print(item)def condition01(item): return item % 2 == 0def condition02(item): return item > 10def condition03(item): return 10 < item < 50def find(func_condition): for item in list01: if func_condition(item) : yield itemfor item in find(condition01): print(item)for item in find(condition02): print(item)for item in find(condition03): print(item)#方法参数,如果传递10/“张无忌"/True,叫做传递数据。#方法参数,如果函数1/函数2/函数3,叫做传递逻辑。
练习2:
在list_helper.py 中,定义通用的查找满足条件的单个对象。
案例:
查找名称是“葵花宝典"的技能。
查找编号是101的技能。
查找持续时间大于0的技能.
建议:
1.先将所有功能实现
2.封装变化(将变化点单独定义为函数)
定义不变的函数
3.将不变的函数转移到list_helper.py 中。
4.在当前模块测试。
list_helper.py
""" 列表助手模块"""class ListHelper: """ 列表助手类 """ @staticmethod def find_all(list_target,func_condition): """ 通用的查找多个元素方法 :param list_target:需要查找的列表 :param func_condition:需要查找的条件,函数类型 函数名(参数)--》bool :return:需要查找的元素,生成器类型 """ for item in list_target: if func_condition(item): yield item @staticmethod def find_single(list_target,func_condition): """ 通用的查找单个元素方法 :param list_target:需要查找的列表 :param func_condition:需要查找的条件,函数类型 函数名(参数)--》bool :return:需要查找的元素 """ for item in list_target: if func_condition(item): return item
exercise01.py
""" 测试01"""from common.list_helper import *class SkillData: def __init__(self,id,name,atk_ratio,duration): """ 技能信息 :param id:技能编号 :param name:技能名称 :param atk_ratio: 攻击比例 :param duration: 持续时间 """ self.id = id self.name = name self.atk_ratio = atk_ratio self.duraftion = duration def __str__(self): return "技能数据是:%d,%s,%d,%d"%(self.id,self.name,self.atk_ratio,self.duraftion)list_skill = [ SkillData(101, "乾坤大挪移",5, 10), SkillData(102, "降龙十八掌", 8, 5), SkillData(103, "葵花宝典",10,2),]def condition01(item): return item.atk_ratio > 6def condition02(item): return 4 < item.duraftion < 11def condition03(item): return len(item.name)> 4 and item.duraftion <6generate01 = ListHelper.find_all(list_skill,condition01)for item in generate01: print(item)
exercise02.py
""" 测试02"""from common.list_helper import *class SkillData: def __init__(self,id,name,atk_ratio,duration): """ 技能信息 :param id:技能编号 :param name:技能名称 :param atk_ratio: 攻击比例 :param duration: 持续时间 """ self.id = id self.name = name self.atk_ratio = atk_ratio self.duraftion = duration def __str__(self): return "技能数据是:%d,%s,%d,%d"%(self.id,self.name,self.atk_ratio,self.duraftion)list_skill = [ SkillData(101, "乾坤大挪移",5, 10), SkillData(102, "降龙十八掌", 8, 5), SkillData(103, "葵花宝典",10,2),]def condition01(item): return item.name == "葵花宝典"def condition02(item): return item.id == 101def condition03(item): return item.duraftion > 0re= ListHelper.find_single(list_skill,condition03)print(re)
函数式编程(函数作为参数)
将核心逻辑传入方法体,使该方法的适用性更广,体现了面向对象的开闭原则。
lambda表达式
知识点
定义:是一种匿名方法。
作用:作为参数传递时语法简洁,优雅,代码可读性强。随时创建和销毁,减少程序耦合度。
说明:形参没有可以不填,方法体只能有一条语句,且不支持赋值语句。
""" lambda 匿名函数 语法: lambda 参数列表:函数体 注意:函数体自带return"""from common.list_helper import *list01 = [43,4,5,5,6,7,87]# def condition01(item):# return item % 2 == 0## def condition02(item):# return item > 10## def condition03(item):# return 10 < item < 50## for item in ListHelper.find_all(list01,condition02):# print(item)for item in ListHelper.find_all(list01,lambda item:item % 2 == 0): print(item)#-----------------------------------------#无参数函数 --> lambdadef fun01(): return 100#等价于a = lambda :100print(a())#多参数函数 --> lambdadef fun02(p1,p2): return p1> p2b = lambda p1,p2:p1>p2print(b(1,2))#无返回值函数 --> lambdadef fun03(p1): print("参数是:" ,p1)c = lambda p1:print("参数是:" ,p1)c(10)#方法体只能有一条语句﹐且不支持赋值语句def fun04(p1): p1 = 2# d = lambda p1:p1=2
练习
使用def定义的函数,改为用lambda定义。
""" 测试03"""from common.list_helper import *class SkillData: def __init__(self,id,name,atk_ratio,duration): """ 技能信息 :param id:技能编号 :param name:技能名称 :param atk_ratio: 攻击比例 :param duration: 持续时间 """ self.id = id self.name = name self.atk_ratio = atk_ratio self.duraftion = duration def __str__(self): return "技能数据是:%d,%s,%d,%d"%(self.id,self.name,self.atk_ratio,self.duraftion)list_skill = [ SkillData(101, "乾坤大挪移",5, 10), SkillData(102, "降龙十八掌", 8, 5), SkillData(103, "葵花宝典",10,2),]generate01 = ListHelper.find_all(list_skill,lambda item : item.atk_ratio > 6)for item in generate01: print(item)generate01 = ListHelper.find_all(list_skill,lambda item : 4 < item.duraftion < 11)print("------------------------------")for item in generate01: print(item)generate01 = ListHelper.find_all(list_skill,lambda item : len(item.name)> 4 and item.duraftion <6)print("------------------------------")for item in generate01: print(item)
练习2:定义敌人类(姓名,攻击力,防御力,血量),创建敌人列表,使用list_helper实现下列功能。
(1)查找姓名是"灭霸"的敌人。
(2)查找攻击力大于10的所有敌人。
(3)查找活的敌人数量。
在list_helper中增加判断是否存在某个对象的方法,返回值:true/false
案例1:判断敌人列表中是否存在"成昆"。
案例2:判断敌人列表中是否攻击力小于5或者防御力小于10的敌人。
步骤:
实现每个需求/单独封装变化/定义不变的函数(“继承”/“多态”)
将不变的函数提取到list_helper.py中。
体会∶函数式编程的思想(“封装﹐继承﹐多态")
在list_helper. py中增加通用的求和方法。
案例1:计算敌人列表中所有敌人的总血量。
案例2:计算敌人列表中所有敌人的总攻击力。
案例3:计算敌人列表中所有敌人的总防御力。
步骤∶实现具体功能/提取变化/提取不变/组合。
在list_helper. py中增加通用的筛选方法。
案例1:获取敌人列表中所有敌人的名称。
案例2:获取敌人列表中所有敌人的攻击力。
案例3:获取敌人列表中所有敌人的名称和血量。
在list_helper.py中增加通用的获取最大值方法。
案例1:获取敌人列表中攻击力最大的敌人。
案例2:获取敌人列表中防御力最大的敌人。
案例3:获取敌人列表中血量最高的敌人。
在list_helper.py中增加通用的升序排列方法。
案例1:将敌人列表按照攻击力进行升序排列。
案例2:将敌人列表按照防御力进行升序排列。
案例3:将敌人列表按照血量进行升序排列。
list_helper.py
""" 列表助手模块"""class ListHelper: """ 列表助手类 """ @staticmethod def find_all(list_target,func_condition): """ 通用的查找多个元素方法 :param list_target:需要查找的列表 :param func_condition:需要查找的条件,函数类型 函数名(参数)--》bool :return:需要查找的元素,生成器类型 """ for item in list_target: if func_condition(item): yield item @staticmethod def find_single(list_target,func_condition): """ 通用的查找单个元素方法 :param list_target:需要查找的列表 :param func_condition:需要查找的条件,函数类型 函数名(参数)--》bool :return:需要查找的元素 """ for item in list_target: if func_condition(item): return item @staticmethod def get_value_number(list_target,func_condition): """ 通用的获取元素的数量 :param list_target:需要查找的列表 :param func_condition:需要查找的条件,函数类型 函数名(参数)--》bool :return:数量 """ value_number = 0 for item in list_target: if func_condition(item): value_number += 1 return value_number @staticmethod def is_exist(list_target,func_condition): """ 通用的判断是否存在某个对象 :param list_target:需要查找的列表 :param func_condition:需要查找的条件,函数类型 函数名(参数)--》bool :return:true/false,true表示存在,false不存在 """ for item in list_target: if func_condition(item): return True return False @staticmethod def get_total_sum(list_target,func_condition): """ 通用的求和方法. :param list_target:需要求和的列表 :param func_condition:需要求和的处理逻辑,函数类型 函数名(参数)--》int/float :return:总和 """ sum = 0 for item in list_target: sum += func_condition(item) return sum @staticmethod def get_sift_value(list_target,func_condition): """ 通用的筛选方法 :param list_target:需要筛选的列表 :param func_condition:需要筛选的处理逻辑,函数类型 函数名(参数)--》int/元组/str/其它类型的对象 :return:生成器 """ # list= [] # for item in list_target: # list.append(func_condition(item)) # return list for item in list_target: yield func_condition(item) @staticmethod def get_max_value(list_target,func_condition): """ 通用的获取最大值方法 :param list_target:需要搜索的列表 :param func_condition:需要筛选的处理逻辑,函数类型 函数名(参数)--》int/str :return:最大元素对象 """ # max_value = 0 # for item in list_target: # if max_value < func_condition(item): # max_value = func_condition(item) # return max_value max_value = list_target[0] for i in range(1,len(list_target)): if func_condition(max_value) < func_condition(list_target[i]): max_value = list_target[i] return max_value @staticmethod def get_incrasing_soft(list_target,func_condition): """ 通用的升序排列方法 :param list_target:需要排序的列表 :param func_condition:需要排序的处理逻辑,函数类型 函数名(参数)--》int/float,需要比较的数据 """ #取出前几个数据 for r in range(len(list_target)-1): #与后面进行对比 for c in range(r+1,len(list_target)): if func_condition(list_target[r]) > func_condition(list_target[c]): list_target[r],list_target[c] = list_target[c],list_target[r]
exercise04.py
from common.list_helper import *class Enemy: def __init__(self,name,atk,defence,hp): self.name = name self.atk = atk self.defence = defence self.hp = hp def __str__(self): return "敌人的信息是:%s,%d,%d,%d"%(self.name,self.atk,self.defence,self.hp)list_enemy = [ Enemy("张三",100,300,100), Enemy("李四",50,4,10), Enemy("成昆",2,3,0)]re = ListHelper.find_single(list_enemy,lambda item:item.name == "成昆")print(re)generator = ListHelper.find_all(list_enemy,lambda item:item.atk > 10)# for item in generator:# print(item)#生成器-->惰性操作#优势∶节省内存#缺点∶获取结果不灵活(不能使用索引╱切片访问结果)#解决∶惰性操作-->立即操作list_result = list(generator)print(list_result)for item in list_result[:1]: print(item)re= ListHelper.get_value_number(list_enemy,lambda item:item.hp > 0)print(re)re= ListHelper.is_exist(list_enemy,lambda item:item.name == "成昆")print(re)re= ListHelper.is_exist(list_enemy,lambda item:item.atk < 5 or item.defence < 10)print(re)
exercise05.py
from common.list_helper import *class Enemy: def __init__(self,name,atk,defence,hp): self.name = name self.atk = atk self.defence = defence self.hp = hplist_enemy = [ Enemy("张三",100,300,100), Enemy("李四",50,4,10), Enemy("成昆",2,3,0)]re = ListHelper.get_total_sum(list_enemy,lambda item:item.hp)print(re)re = ListHelper.get_total_sum(list_enemy,lambda item:item.atk)print(re)re = ListHelper.get_total_sum(list_enemy,lambda item:item.defence)print(re)
exercise06.py
from common.list_helper import *class Enemy: def __init__(self,name,atk,defence,hp): self.name = name self.atk = atk self.defence = defence self.hp = hplist_enemy = [ Enemy("张三",100,300,100), Enemy("李四",50,4,10), Enemy("成昆",2,3,0)]for item in ListHelper.get_sift_value(list_enemy,lambda item:item.name): print(item)for item in ListHelper.get_sift_value(list_enemy,lambda item:item.atk): print(item)for item in ListHelper.get_sift_value(list_enemy,lambda item:(item.name,item.hp)): print(item)
exercise07.py
from common.list_helper import *class Enemy: def __init__(self,name,atk,defence,hp): self.name = name self.atk = atk self.defence = defence self.hp = hp def __str__(self): return "敌人的信息是:%s,%d,%d,%d"%(self.name,self.atk,self.defence,self.hp)list_enemy = [ Enemy("张三",100,300,100), Enemy("李四",50,4,10), Enemy("成昆",2,3,0)]re = ListHelper.get_max_value(list_enemy,lambda item:item.atk)print(re)re = ListHelper.get_max_value(list_enemy,lambda item:item.defence)print(re)re = ListHelper.get_max_value(list_enemy,lambda item:item.hp)print(re)
exercise08.py
from common.list_helper import *class Enemy: def __init__(self,name,atk,defence,hp): self.name = name self.atk = atk self.defence = defence self.hp = hp def __str__(self): return "敌人的信息是:%s,%d,%d,%d"%(self.name,self.atk,self.defence,self.hp)list_enemy = [ Enemy("张三",100,300,100), Enemy("李四",50,1,10), Enemy("成昆",2,3,0)]ListHelper.get_incrasing_soft(list_enemy,lambda item:item.atk)for item in list_enemy: print(item)print("-------------------------------")ListHelper.get_incrasing_soft(list_enemy,lambda item:item.defence)for item in list_enemy: print(item)print("-------------------------------")ListHelper.get_incrasing_soft(list_enemy,lambda item:item.hp)for item in list_enemy: print(item)
内置高阶函数
map(函数,可迭代对象)
filter(函数,可迭代对象)
sorted(可迭代对象,key =函数, reverse = bool值)
max(可迭代对象,key =函数)
min(可迭代对象,key =函数)
""" 内置高阶函数"""from common.list_helper import *class Enemy: def __init__(self,name,atk,defence,hp): self.name = name self.atk = atk self.defence = defence self.hp = hp def __str__(self): return "敌人的信息是:%s,%d,%d,%d"%(self.name,self.atk,self.defence,self.hp)list_enemy = [ Enemy("张三",100,300,100), Enemy("李四",50,1,10), Enemy("成昆",2,3,0)]#1.filter:根据条件筛选可迭代对象中的元素﹐返回值为新可迭代对象。#需求:获取所有活人for item in ListHelper.find_all(list_enemy,lambda item:item.hp > 0): print(item)#等价于re = filter(lambda item:item.hp > 0 ,list_enemy)for item in re: print(item)#2.map:通用的筛选方法#需求:获取所有敌人的名字for item in ListHelper.get_sift_value(list_enemy,lambda item:item.name): print(item)#等价于re = map(lambda item:item.name ,list_enemy)for item in re: print(item)#3.max:获取最大值#需求:获取血量最大的敌人print(ListHelper.get_max_value(list_enemy,lambda item:item.hp))print(max(list_enemy,key =lambda item:item.hp ))#4.min:获取最小值#略#5.sort# 内部直接修改列表,使用时无需通过返回值获取数据# ListHelper.get_incrasing_soft(list_enemy,lambda item:item.atk)# for item in list_enemy:# print(item)# print()## #内部返回新列表﹐使用时必须获取返回值。# re = sorted(list_enemy,key = lambda item:item.atk )# for item in re:# print(item)#支持降序排列re = sorted(list_enemy,key = lambda item:item.atk,reverse=True )for item in re: print(item)
练习
1:([1,1,1],[2,2],[3,3,3,3])获取元组中长度最大的列表。
2:根据敌人列表,获取所有敌人的姓名与血量与攻击力。
3:在敌人列表中,获取攻击力大于90的所有活人。
4:根据防御力对敌人列表进行降序排列。
class Enemy: def __init__(self,name,atk,defence,hp): self.name = name self.atk = atk self.defence = defence self.hp = hp def __str__(self): return "敌人的信息是:%s,%d,%d,%d"%(self.name,self.atk,self.defence,self.hp)list_enemy = [ Enemy("张三",100,300,100), Enemy("李四",50,1,10), Enemy("成昆",2,3,0)]tuple01 = ([1,1,1],[2,2],[3,3,3,3])print(max(tuple01,key = lambda item:len(item)))print(min(tuple01,key = lambda item:len(item)))for item in map(lambda item:(item.name,item.hp,item.atk),list_enemy): print(item)for item in filter(lambda item:item.atk > 90 and item.hp > 0,list_enemy): print(item)for item in sorted(list_enemy,key = (lambda item:item.atk > 90 and item.hp > 0),reverse=True): print(item)
外部嵌套作用域
""" 外部嵌套作用域"""def fun01(): # 是fun01函数的局部作用域 # 也是fun02函数的外部嵌套作用域 a = 1 def fun02(): b = 2 # 可以访问外部嵌套作用域变量# print(a)#1# 不能修改外部嵌套作用城变量# a = 2#创建了fun02的局部变量# print(a)#2 nonlocal a#声明外部嵌套作用域 a = 2 fun02() print(a)#第一次1,第二次2 fun01()
总结
面向对象编程∶考虑问题从对象的角度出发。函数式编程∶考虑问题从函数的角度出发。“ 封装”:封装变化点。“继承":抽象/隔离变化。“多态":调用抽象的函数变量,执行具体的个性函数。lambda:匿名方法,作为实参def 功能1():共性代码个性1代码def 功能2()∶共性代码个性2代码def 功能3():共性代码个性3代码"封装"def 个性1():个性1代码def 个性2():个性2代码def 个性3():个性3代码"继承"#函数类型变量就是具体共性函数的抽象def 共性(函数类型变量):共性代码#多态函数类型变量() --> 执行具体个性代码"执行"共性(个性1)项目中的使用:将共性代码提取到单独的模块中在某个代码中导入模块from common.list_helper import *定义个性代码def 个性代码():...调用静态方法(共性代码)结果 = ListHelper.静态方法(要操作的数据,个性代码)def 方法名(参数):函数体结果 = ListHelper.静态方法(要操作的数据,lambda 参数:函数体)生成器-->惰性操作优势∶节省内存缺点∶获取结果不灵活(不能使用索引切片访问结果)解决∶惰性操作-->立即操作