【Python 高级】Python全栈体系(九)

Python 高级

第五章 函数式编程

  • 定义:用一系列函数解决问题。
    • 函数可以赋值给变量,赋值后变量绑定函数。
    • 允许将函数作为参数传入另一个函数。
    • 允许函数返回一个函数。
  • 高阶函数:将函数作为参数或返回值的函数。

一、函数作为参数

  • 将核心逻辑传入方法体,使该方法的适用性更广,体现了面向对象的开闭原则。
"""
    函数式编程 - 语法
"""
def func01():
    print("func01执行")

a = func01
a()

def func02():
    print("func02执行")

# 通用
def func03(func):
    print("func03执行")
    func()

func03(func02)
func03(func01)
"""
    函数式编程 - 思想
"""
list01 = [4, 54, 56, 65, 67, 7]


# 需求1:定义函数,在列表中查找所有大于50的数字
def find01():
    for item in list01:
        if item > 50:
            yield item


# 需求2:定义函数,在列表中查找所有小于10的数字
def find02():
    for item in list01:
        if item < 10:
            yield item


# “封装” -- 分
def condition01(item):
    return item > 50


def condition02(item):
    return item < 10

# 通用
# “继承” - 隔
def find(func):
    for item in list01:
        # if item < 10:
        # if condition02(item):
        if func(item):
            yield item


# "多态" - 做
for item in find(condition01):
    print(item)

for item in find(condition02):
    print(item)
"""
    练习1:在老婆列表中,查找颜值大于90的所有老婆
    练习2:在老婆列表中,查找身高小于170的所有老婆
"""


class Wife:
    def __init__(self, name="", face_score=0, age=0, height=0):
        self.name = name
        self.face_score = face_score
        self.age = age
        self.height = height


list_wife = [
    Wife("双儿", 96, 22, 166),
    Wife("阿珂", 100, 23, 173),
    Wife("小郡主", 96, 22, 161),
    Wife("方怡", 86, 27, 166),
    Wife("苏荃", 99, 31, 176),
    Wife("建宁", 93, 24, 163),
    Wife("曾柔", 88, 26, 170),
]


def find01():
    for item in list_wife:
        if item.face_score > 90:
            yield item


def find02():
    for item in list_wife:
        if item.height < 170:
            yield item


def condition01(item):
    return item.face_score > 90


def condition02(item):
    return item.height < 170


def find(func):
    for item in list_wife:
        # if item.face_score > 90:
        # if condition01(item):
        if func(item):
            yield item

for item in find(condition01):
    print(item)

for item in find(condition02):
    print(item)
"""
    可迭代对象工具模块
"""


class IterableHelper:

    @staticmethod
    def find_all(iterable, func_condition):
        """
            在可迭代对象中查找满足条件的所有元素
        :param iterable: 可迭代对象类型,需要查找的数据
        :param func_condition:函数类型,查找的条件
        :return:生成器对象
        """
        for item in iterable:
            if func_condition(item):
                yield item

    @staticmethod
    def first(iterable, func_condition):
        """
            在可迭代对象中查找第一个满足条件的元素
        :param iterable:可迭代对象类型,需要查找的数据
        :param func_condition:函数类型,查找的条件
        :return:第一个满足条件的元素
        """
        for item in iterable:
            if func_condition(item):
                return item

    @staticmethod
    def get_count(iterable, func_condition):
        """
            在可迭代对象中,获取满足条件的元素数量
        :param iterable:可迭代对象类型,需要查找的数据
        :param func_condition:函数类型,查找的条件
        :return:int类型,数量
        """
        count = 0
        for item in iterable:
            if func_condition(item):
                count += 1
        return count

    @staticmethod
    def select(iterable, func_handle):
        """
            通用的筛选方法
        :param iterable:可迭代对象类型,需要筛选的数据
        :param func_handle:筛选的逻辑
        :return:生成器对象
        """
        for item in iterable:
            yield func_handle(item)

    @staticmethod
    def is_exists(iterable, func_condition):
        """
            判断可迭代对象中是否存在某个条件的对象
        :param iterable:可迭代对象类型,需要筛选的数据
        :param func_condition:查找的条件
        :return:bool,True表示存在,False表示不存在
        """
        for item in iterable:
            if func_condition(item):
                return True
        return False

    @staticmethod
    def sum(iterable, func_handle):
        """
            根据指定逻辑累加可迭代对象中的元素
        :param iterable:可迭代对象类型,需要累加的数据
        :param func_handle:累加逻辑
        :return:数值类型,累加结果
        """
        sum_value = 0
        for item in iterable:
            sum_value += func_handle(item)
        return sum_value

    @staticmethod
    def get_max(iterable, func_condition):
        """
            根据条件在可迭代对象中获取最大元素
        :param iterable:可迭代对象类型,需要查找的数据
        :param func_condition:指定条件
        :return:最大元素
        """
        max_value = iterable[0]
        for i in range(1, len(iterable)):
            # if max_value.face_score < iterable[i].face_score:
            # if max_value.height < iterable[i].height:
            if func_condition(max_value) < func_condition(iterable[i]):
                max_value = iterable[i]
        return max_value

    @staticmethod
    def delete_all(iterable, func_condition):
        """
             根据条件删除多个元素
        :param iterable: 可迭代对象类型,需要删除的数据
        :param func_condition:删除条件
        :return:删除的元素数量
        """
        count = 0
        for i in range(len(iterable) - 1, -1, -1):
            if func_condition(iterable[i]):
                del iterable[i]
                count += 1
        return count

    @staticmethod
    def order_by(iterable, func_condition):
        """
            根据条件升序排列
        :param iterable:可迭代对象类型,需要排序的数据
        :param func_condition:比较条件
        """
        for r in range(len(iterable) - 1):
            for c in range(r + 1, len(iterable)):
                if func_condition(iterable[r]) > func_condition(iterable[c]):
                    iterable[r], iterable[c] = iterable[c], iterable[r]
"""
    需求1:
        1. 在老婆列表中查找方怡对象
        2. 在老婆列表中查找颜值大于95的单个老婆对象
        first
    需求2:
        1. 计算老婆列表中姓名大于2个字的老婆数量
        2. 计算老婆列表年龄小于25的老婆数量
        get_count

    需求3:
        1. 获取老婆列表中所有老婆的姓名
        2. 获取老婆列表中所有老婆的姓名与颜值
        select

    需求4:
        1. 在老婆列表中判断是否存在姓名是苏荃的元素
        2. 在老婆列表中判断是否存在高度大于170的元素
        is_exists

    需求5:
        1. 累加老婆列表中所有人的年龄
        2. 累加老婆列表中所有人的高度
        sum

    需求7:
        1. 在老婆列表中找出颜值最高的老婆对象
        2. 在老婆列表中找出年龄最大的老婆对象
        get_max

    需求8:
        1. 在老婆列表中删除年龄小于25的所有老婆
        2. 在老婆列表中删除身高大于170的所有老婆
        delete_all

    需求9:
        1. 对老婆列表根据年龄进行升序排列
        2. 对老婆列表根据颜值进行升序排列
        order_by

    步骤:
        1. 根据需求,定义函数.
        2. 将变化点单独定义为函数.
        3. 将通用代码定义位函数(使用参数隔离变化点)
        4. 在IterableHelper类中添加新功能
        5. 在当前模块中进行测试
"""
from common.iterable_tools import IterableHelper


class Wife:
    def __init__(self, name="", face_score=0, age=0, height=0):
        self.name = name
        self.face_score = face_score
        self.age = age
        self.height = height

    def __str__(self):
        return "%s-%d-%d-%d"%(self.name,self.face_score,self.age,self.height)


list_wife = [
    Wife("双儿", 96, 22, 166),
    Wife("阿珂", 100, 23, 173),
    Wife("小郡主", 96, 22, 161),
    Wife("方怡", 86, 27, 166),
    Wife("苏荃", 99, 31, 176),
    Wife("建宁", 93, 24, 163),
    Wife("曾柔", 88, 26, 170),
]


# def condition01(item):
#     return item.face_score > 90


# for item in IterableHelper.find_all(list_wife,condition01):
#     print(item)

for item in IterableHelper.find_all(list_wife,lambda item:item.face_score > 90):
    print(item)

# 练习1:
# def first01():
#     for item in list_wife:
#         if item.name == "方怡":
#             return item
#
# def first02():
#     for item in list_wife:
#         if item.face_score > 95:
#             return item

# def condition01(item):
#     return item.name == "方怡"
#
# def condition02(item):
#     return item.face_score > 95

# def first(func):
#     for item in list_wife:
#         # if item.face_score > 95:
#         # if condition02(item):
#         if func(item):
#             return item

# print(IterableHelper.first(list_wife,condition02))
print(IterableHelper.first(list_wife,lambda item:item.face_score > 95))

# 练习2:
# def get_count01():
#     count = 0
#     for item in list_wife:
#         if len(item.name) > 2:
#             count += 1
#     return count
# def get_count02():
#     count = 0
#     for item in list_wife:
#         if item.age < 25:
#             count += 1
#     return count

# def condition01(item):
#     return len(item.name) > 2
#
# def condition02(item):
#     return item.age < 25

# def get_count(func):
#     count = 0
#     for item in list_wife:
#         # if item.age < 25:
#         # if condition02(item):
#         if func(item):
#             count += 1
#     return count

# print(IterableHelper.get_count(list_wife,condition02))
print(IterableHelper.get_count(list_wife,lambda item: item.age < 25))

# 练习3
# def select01():
#     for item in list_wife:
#         yield item.name
#
# def select02():
#     for item in list_wife:
#         yield (item.name,item.face_score)

def handle01(item):
    return item.name

def handle02(item):
    return (item.name,item.face_score)

# def select(func):
#     for item in list_wife:
#         # yield (item.name,item.face_score)
#         # yield handle02(item)
#         yield func(item)

for item in IterableHelper.select(list_wife,handle02):
    print(item)


# 练习4:

# def is_exists01():
#     for item in list_wife:
#         if item.name == "苏荃":
#             return True
#     return False
#
# def is_exists02():
#     for item in list_wife:
#         if item.height > 170:
#             return True
#     return False
#
# def condition01(item):
#     return item.name == "苏荃"
#
# def condition02(item):
#     return item.height > 170
#
# def is_exists(func):
#     for item in list_wife:
#         # if item.height > 170:
#         # if condition02(item):
#         if func(item):
#             return True
#     return False

print(IterableHelper.is_exists(list_wife,lambda item:item.height > 170))

# 练习5:
# def sum01():
#     sum_value = 0
#     for item in list_wife:
#         sum_value += item.age
#     return sum_value
#
# def sum02():
#     sum_value = 0
#     for item in list_wife:
#         sum_value += item.height
#     return sum_value
#
# def sum(func):
#     sum_value = 0
#     for item in list_wife:
#         # sum_value += item.height
#         sum_value += func(item)
#     return sum_value

print(IterableHelper.sum(list_wife,lambda item:item.height))

# 练习6:
print(IterableHelper.get_max(list_wife,lambda element:element.height))

# 练习7:
# print(IterableHelper.delete_all(list_wife,lambda e:e.age > 25))

# 练习8:
IterableHelper.order_by(list_wife,lambda e:e.age)
for item in list_wife:
    print(item)
1. lambda 表达式
  1. 定义:是一种匿名方法。
  2. 作用:作为参数传递时语法简洁,优雅,代码可读性强。
    随时创建和销毁,减少程序耦合度。
  3. 语法
# 定义:
变量 = lambda 形参: 方法体
# 调用:
变量(实参)
  1. 说明:
    – 形参没有可以不填
    – 方法体只能有一条语句,且不支持赋值语句。
"""
    lambda表达式
        匿名方法
        语法:
            lambda 参数:方法体
"""
# def func01(a,b):
#     return a > b
#
# print(func01(10,20))

# 1. 有参数有返回值
func01 = lambda a,b:a > b
print(func01(10,20))

# 2. 无参数有返回值
# def func02():
#     return "ok"
#
# print(func02())
func02 = lambda :"ok"
print(func02())

# 3. 无参数无返回值
# def func03():
#     print("ok")
#
# func03()

func03 = lambda :print("ok")
func03()

# 4. 有参数无返回值
# def func03(a):
#     print(a)
#
# func03(100)
func03 = lambda a:print(a)
func03(100)

# 5. lambda 不支持赋值语句
# def func05(iterable):
#     iterable[0] = 100
#
# list01 = [1]
# func05(list01)
# print(list01)

# func05 = lambda iterable: iterable[0] = 100

# 6. lambda 不支持多条语句
# def func06(a,b):
#     print(a)
#     print(b)
#
# func06(10,20)

# func06 = lambda a,b: print(a);print(b)
2. 内置高阶函数
  1. map(函数,可迭代对象):使用可迭代对象中的每个元素调用函数,将返回值作为新可迭代对象元素;返回值为新可迭代对象。
  2. filter(函数,可迭代对象):根据条件筛选可迭代对象中的元素,返回值为新可迭代对象。
  3. sorted(可迭代对象,key = 函数,reverse = bool值):排序,返回值为排序结果。
  4. max(可迭代对象,key = 函数):根据函数获取可迭代对象的最大值。
  5. min(可迭代对象,key = 函数):根据函数获取可迭代对象的最小值。
"""
    内置高阶函数
        这个函数的参数或者返回值是函数
    练习:exercise02
"""
class Wife:
    def __init__(self, name="", face_score=0, age=0, height=0):
        self.name = name
        self.face_score = face_score
        self.age = age
        self.height = height

    def __str__(self):
        return "%s-%d-%d-%d" % (self.name, self.face_score, self.age, self.height)


list_wife = [
    Wife("双儿", 96, 22, 166),
    Wife("阿珂", 100, 23, 173),
    Wife("小郡主", 96, 22, 161),
    Wife("方怡", 86, 27, 166),
    Wife("苏荃", 99, 31, 176),
    Wife("建宁", 93, 24, 163),
    Wife("曾柔", 88, 26, 170),
]

# 1.  map 映射
#  在老婆列表中获取所有名称
#  类似于:select
for element in map(lambda item: item.name, list_wife):
    print(element)

# 2. filter 过滤器
# 在老婆列表中获取颜值大于90的所有老婆
#  类似于:find_all
for element in filter(lambda item: item.face_score > 90, list_wife):
    print(element)


# 3. max/min
# 在老婆列表中获取颜值最高的老婆
#  类似于:get_max
print(max(list_wife,key = lambda item:item.face_score))
print(min(list_wife,key = lambda item:item.face_score))

# 4.sorted 排序
#   注意:没有改变原有列表,而是返回新的
# 升序
for item in sorted(list_wife,key = lambda item:item.height):
    print(item)
# 降序
for item in sorted(list_wife,key = lambda item:item.height,reverse=True):
    print(item)

二、函数作为返回值

  • 逻辑连续,当内部函数被调用时,不脱离当前的逻辑。
"""
    外部嵌套作用域
"""

def func01():
    a = 10

    def func02():
        # 内部函数,可以访问外部嵌套变量
        # print(a)
        # 内部函数,如果修改外部嵌套变量,需要使用nonlocal语句声明
        nonlocal a
        a = 20

    func02()
    print(a)

func01()
1. 闭包
1.1 三要素
  • 必须有一个内嵌函数。
  • 内嵌函数必须引用外部函数中变量。
  • 外部函数返回值必须是内嵌函数。
1.2 语法
  • 定义
def 外部函数名(参数):
	外部变量
	def 内部函数名(参数):
		使用外部变量
	return 内部函数名
  • 调用
变量 = 外部函数名(参数)
变量(参数)
1.3 定义
  • 在一个函数内部的函数,同时内部函数又引用了外部函数的变量。
1.4 本质
  • 闭包是将内部函数和外部函数的执行环境绑定在一起的对象。
1.5 优点
  • 内部函数可以使用外部变量。
1.6 缺点
  • 外部变量一直存在于内存中,不会在调用结束后释放,占用内存。
1.7 作用
  • 实现python装饰器。
"""
    闭包
        三大要素:
            具有内外函数
            内部函数访问外部函数变量
            外部函数返回内部函数
        字面意思:封闭程序运行环境  --> 保存
        体现:
            外部函数执行过后,栈帧不释放,等待内部函数使用.
"""
def func01():
    a = 100
    def func02():
        print(a)
    return func02

# 调用外部函数,返回内部函数
result = func01()

# 因为python支持闭包,所以在外部函数执行过后,栈帧没有释放.
# 因此内部函数执行时,可以正确访问外部嵌套变量.
result()
"""
    闭包应用
        逻辑连续
        装饰器
"""

def give_gife_money(money):
    print("得到了", money, "元压岁钱")

    def child_buy(target, price):
        nonlocal money
        money -= price
        print("购买了", target, "还剩", money, "元")

    return child_buy

action = give_gife_money(500)
action("变形金刚", 130)
action("遥控飞机", 250)
action("零食", 120)
2. 装饰器 decorator
2.1 定义
  • 在不改变原函数的调用以及内部代码情况下,为其添加新功能的函数。
2.2 语法
def 函数装饰器名称(func):
    def 内嵌函数(*args, **kwargs):
        需要添加的新功能
        return func(*args, **kwargs)
return内嵌函数

原函数 = 内嵌函数
@ 函数装饰器名称
def 原函数名称(参数):
	函数体

原函数(参数)
2.3 本质
  • 使用“@函数装饰器名称”修饰原函数,等同于创建与原函数名称相同的变量,关联内嵌函数;故调用原函数时执行内嵌函数。
  • 原函数名称 = 函数装饰器名称(原函数名称)
2.4 装饰器链
  • 一个函数可以被多个装饰器修饰,执行顺序为从近到远。
"""
    装饰器
"""


def func01():
    print("func01执行喽")
    return "ok"


def func02(a):
    print(a, "func02执行喽")


def print_func_name(func):
    def wrapper(*args, **kwargs):  # 合
        # 新功能
        print(func.__name__)
        # 旧功能
        return func(*args, **kwargs)  # 拆

    return wrapper


# func01 = 新功能  +  旧功能
# func01 = print_func_name + func01
func01 = print_func_name(func01)

print(func01())  # 执行的是内部函数

# func02 = print_func_name(func02)

# func02(100)
"""
    装饰器
"""
def print_func_name(func):
    def wrapper(*args, **kwargs):  # 合
        # 新功能
        print(func.__name__)
        # 旧功能
        return func(*args, **kwargs)  # 拆

    return wrapper

@print_func_name# func01 = print_func_name(func01)
def func01():
    print("func01执行喽")
    return "ok"

@print_func_name # func02 = print_func_name(func02)
def func02(a):
    print(a, "func02执行喽")

print(func01())  # 执行的是内部函数

func02(100)
"""
    在不改变原有功能的定义与调用情况下(进入后台、删除订单),
    为其增加新功能(验证权限).
"""
def verify_permissions(func):
    def wrapper(*args, **kwargs):  # 合
        # 新功能
        print("验证权限")
        # 旧功能
        return func(*args, **kwargs)  # 拆

    return wrapper

@verify_permissions
def enter_background():
    print("进入后台")

@verify_permissions
def delete_order():
    print("删除订单")

# enter_background = verify_permissions(enter_background)
# delete_order = verify_permissions(delete_order)

enter_background()
delete_order()
"""
    在不改变原有功能的定义与调用情况下,为其增加新功能.
"""
import time


def print_execute_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        stop_time = time.time()
        print(stop_time - start_time)
        return result

    return wrapper


@print_execute_time
def func01():
    sum_value = 0
    for i in range(100):
        sum_value += i
    return sum_value


@print_execute_time
def func02(n):
    sum_value = 0
    for i in range(n):
        sum_value += i
    return sum_value


func01()

func02(100000)

你可能感兴趣的:(Python高级,python)