【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 item

def find02():
    for item in list_skill:
        if   4 < item.duraftion < 11:
            yield item


def find04():
    for item in list_skill:
        if  len(item.name)> 4 and item.duraftion <6 :
            yield item

#"封装"(分而治之,变而疏之)
#将每个变化的条件,单独定义在函数中。
def condition01(item):
    return item.atk_ratio > 6

def condition02(item):
    return  4 < item.duraftion < 11

def 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 item

for 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 == 0

def condition02(item):
    return  item > 10

def condition03(item):
    return  10 < item < 50

def find(func_condition):
    for item in list01:
        if  func_condition(item) :
            yield item

for 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 > 6

def condition02(item):
    return  4 < item.duraftion < 11

def condition03(item):
    return  len(item.name)> 4 and item.duraftion <6


generate01 = 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 == 101

def condition03(item):
    return  item.duraftion > 0

re= 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)

#-----------------------------------------
#无参数函数 --> lambda
def fun01():
    return 100
#等价于
a = lambda :100
print(a())

#多参数函数 --> lambda
def fun02(p1,p2):
    return p1> p2
b = lambda p1,p2:p1>p2
print(b(1,2))

#无返回值函数 --> lambda
def 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 = hp


list_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 = hp


list_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 参数:函数体)

生成器-->惰性操作
优势∶节省内存
缺点∶获取结果不灵活(不能使用索引切片访问结果)
解决∶惰性操作-->立即操作

你可能感兴趣的:(python核心,python,开发语言,pycharm)