Bootstrap

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

函数式编程

函数式编程(函数作为返回值)

逻辑连续,当内部函数被调用时,不脱离当前的逻辑。

闭包(了解)

三要素:
–必须有一个内嵌函数。
–内嵌函数必须引用外部函数中变量。
–外部函数返回值必须是内嵌函数。
定义:在一个函数内部的函数,同时内部函数又引用了外部函数的变量。
本质:闭包是将内部函数和外部函数的执行环境绑定在一起的对象。

"""
    闭包
"""
def fun01():
    a = 1
    def fun02():
        print(a)
    return fun02

#调用外部函数﹐返回值是内嵌函数
result = fun01()
#调用内嵌函数
result()#可以访问外部变量a

内存图:
在这里插入图片描述
闭包应用:

#闭包应用:逻辑连续﹐当内部函数被调用时﹐不脱离当前的逻辑。
#压岁钱
def give_gift_money(money):
    """
        得到压岁钱
    :return:
    """
    print("得到了%d压岁钱"% money)
    def child_buy(target,price):
        """
            孩子购买商品
        :param target: 需要购买的商品
        :param price: 商品单价
        """
        nonlocal money
        if money >= price:
            money -= price
            print("孩子花了%.1f钱,购买了%s" % (price,target))
        else:
            print("钱不够啦")

    return child_buy

#下列代码是一个连续的逻辑
action = give_gift_money(10000)
action("唐僧肉",0.5)
action("小汽车",2000)
action("手机",8000)
# 得到了10000压岁钱
# 孩子花了0.5钱,购买了唐僧肉
# 孩子花了2000.0钱,购买了小汽车
# 钱不够啦

补充练习

在list_helper.py中新增以下功能:
(1)获取最小值
(2)降序排列
(3)根据指定条件删除元素
案例:在敌人列表中,删除所有活人。
案例:在敌人列表中,攻击力小于50的所有敌人。
案例:在敌人列表中,防御力大于100的所有敌人。

@staticmethod
    def get_min(list_target, func_condition):
        """
            通用的获取最小值方法
        :param list_target:需要搜索的列表
        :param func_condition:需要筛选的处理逻辑,函数类型
            函数名(参数)--int/str
        :return:最小元素对象
        """

        min_value = list_target[0]
        for i in range(1,len(list_target)):
            if func_condition(min_value) > func_condition(list_target[i]):
                min_value = list_target[i]
        return min_value

    @staticmethod
    def order_by_descending(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]

    @staticmethod
    def delete_all(list_target, func_condition):
        """
            通用的根据指定条件删除元素方法
        :param list_target:需要删除的列表
        :param func_condition:需要删除的处理逻辑,函数类型
            函数名(参数)--int/float,需要删除的数据
        """
        #3 2 1 0
        for i in range(len(list_target)-1,-1,-1):
            if func_condition(list_target[i]):
                del list_target[i]
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,50,0)
]

re = ListHelper.get_min(list_enemy, lambda item:item.atk)
print(re)

re = ListHelper.get_min(list_enemy, lambda item:item.defence)
print(re)

re = ListHelper.get_min(list_enemy, lambda item:item.hp)
print(re)

ListHelper.order_by_descending(list_enemy, lambda item:item.atk)
for item in  list_enemy:
    print(item)

print("-------------------------------")

ListHelper.order_by_descending(list_enemy, lambda item:item.defence)
for item in  list_enemy:
    print(item)
print("-------------------------------")

ListHelper.order_by_descending(list_enemy, lambda item:item.hp)
for item in  list_enemy:
    print(item)

# ListHelper.delete_all(list_enemy, lambda item: item.hp > 0)
# for item in  list_enemy:
#     print(item)

print("-------------------------------")

# ListHelper.delete_all(list_enemy, lambda item:item.atk < 50)
# for item in  list_enemy:
#     print(item)
print("-------------------------------")

ListHelper.delete_all(list_enemy, lambda item:item.defence > 100)
for item in  list_enemy:
    print(item)

函数装饰器decorators

定义:在不改变原函数的调用以及内部代码情况下,为其添加新功能的函数。

def 函数装饰器名称(func)
	def 内嵌函数(*args,**kwargs):
		需要添加的新功能
		return func(*args,**kwargs) .					
	return wrapper

@函数装饰器名称.
def 原函数名称(参数):.
	函数体

原函数(参数)

本质:原函数名称=函数装饰器名称(原函数名称)

装饰器链:
一个函数可以被多个装饰器修饰,执行顺序为从近到远。

知识点

"""
    装饰器
"""
# #需要增加的功能
# # def verify_permissions():
# #     print("权限验证")
#
# def verify_permissions(func):
#     def wrapper():
#         print("权限验证")
#         func()
#     return wrapper
#
# #已有功能
# @verify_permissions #4.@+新功能,装饰器
# def enter_background():
#     #1. print("权限验证")
#     #2.verify_permissions()缺点∶增加新功能,需要修改已有功能,违反开闭原则
#     print("进入后台")
#
# @verify_permissions
# def delete_order():
#     # 1.print("权限验证")
#     #2.verify_permissions()缺点∶增加新功能,需要修改已有功能,违反开闭原则
#     print("删除订单")
#
# #enter_background = 新功能 + 旧功能
# # 3.enter_background = verify_permissions(enter_background)缺点:每次拦截对已有功能(enter_background)的调用,不科学
# # 3.delete_order = verify_permissions(delete_order)
# enter_background()
# delete_order()

#需要增加的功能
# def verify_permissions():
#     print("权限验证")

#缺点:如果已有功能参数不统一,则无法包装
# def verify_permissions(func):
#     def wrapper():
#         print("权限验证")
#         func()
#     return wrapper
#
# #已有功能
# @verify_permissions
# def enter_background(login_id,pwd):
#     print("进入后台")
#
# @verify_permissions
# def delete_order(id):
#     print("删除订单")
# enter_background("abc",1234)
# delete_order(101)

def verify_permissions(func):
    def wrapper(*args,**kwargs):#*args,将所有形参合成一个元组传进去,*args位置参数无限个,**kwagrs关键字参数无限
        print("权限验证")
        func(*args,**kwargs)#*args,将一个元组拆成多个参数
    return wrapper

#已有功能
@verify_permissions
def enter_background(login_id,pwd,*,a=1):
    print(login_id,pwd,a,"进入后台")

@verify_permissions
def delete_order(id):
    print("删除订单",id)
enter_background("abc",1234)
delete_order(101)

练习

练习1∶在不改变原有功能(存取钱)的定义与调用情况下,增加验证账号的功能。

def deposit(money):
	print("存%d钱喽" % money)
	
def withdraw(login id, pwd):
	print("取钱喽",login_id,pwd)
	
deposit (10000)
withdraw ("zs",123)
#验证账号
def verify_account(func):
    def wrapper(*args,**kwargs):
        print("验证账号")
        return func(*args,**kwargs)
    return wrapper

@verify_account
def deposit(money):
    print("存%d钱喽" % money)

@verify_account
def withdraw(login_id, pwd):
    print("取钱喽", login_id, pwd)

deposit(10000)
withdraw("zs",123)

练习2:在不改变原有功能(fun01 fun02)调用与定义情况下,为其增加新功能(打印函数执行时间)。

import time
def fun01():
	time.sleep(2)
	print("fun01执行完毕喽")#睡眠2秒,用于模拟程序执行的过程
	
def fun02(a):
	time.sleep(1)
	print("fun02执行完毕喽,参数是:",a)

fun01()
fun02(100)
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

@print_execute_time
def fun01():
    time.sleep(2)
    print("fun01执行完毕喽")

@print_execute_time
def fun02(a):
    time.sleep(1)
    print("fun02执行完毕喽,参数是:", a)


fun01()
fun02(100)

# fun01执行完毕喽
# 执行时间是: 2.0125880241394043
# fun02执行完毕喽,参数是: 100
# 执行时间是: 1.004333734512329

总结

函数式编程
	函数作为参数
		自定义高阶函数 list_helper.py
		内置高阶函数
			map(函数,可迭代对象) --》list_helper.py.筛选方法
			filter(函数,可迭代对象)--》list_helper.py.find_all方法
			max(可迭代对象,key = 函数)
			min(可迭代对象,key = 函数)
			sorted(可迭代对象,key = 函数)--》list_helper.py.升序方法
			sorted(可迭代对象,key = 函数,reverse = True)--》list_helper.py.降序方法	
	函数作为返回值
		闭包
		装饰器
;