> 文档中心 > 【python核心】函数式编程(一)

【python核心】函数式编程(一)

文章目录

  • 函数式编程
    • 语法
    • 思想
    • 练习
  • 函数式编程(函数作为参数)
  • lambda表达式
    • 知识点
    • 练习
  • 内置高阶函数
    • 练习
  • 外部嵌套作用域
  • 总结

函数式编程

定义:用一系列函数解决问题。

  1. 函数可以赋值给变量,赋值后变量绑定函数。
  2. 允许将函数作为参数传入另一个函数。
  3. 允许函数返回一个函数。

高阶函数:将函数作为参数或返回值的函数。

语法

"""    函数式编程 语法"""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 参数:函数体)生成器-->惰性操作优势∶节省内存缺点∶获取结果不灵活(不能使用索引切片访问结果)解决∶惰性操作-->立即操作