闭包和装饰器

今日内容总结

一、闭包函数

二、闭包函数的实际应用

三、装饰器简介

四、简易版本装饰器

五、进阶版本装饰器

六、完整版本装饰器

七、装饰器模板(很重要)

八、装饰器语法糖

九、装饰器修复技术

一、闭包函数

# 闭包函数的两大特征
1、闭:定义在函数内部的函数
2、包:内部函数使用了外层函数名称空间中的名字
eg:
 def outer():
    x = 111
    def inner():
        print('form outer>>>inner',x)
    return inner
x = 222  # 结果和这个x = 222没有关系
res = outer()
res()  # 111

二、闭包函数实际应用

# 闭包函数是给函数传参的另外一种方式
函数体传参的方式:
 1、形参:
 def index(username):
     print(username)
 函数体代码需要什么就可以在形参中写什么
 index('owen')
    
 2、闭包
 def outer():
        username = 'owen'
        def index():
            print(username)
        return index
 res = outer()
 res()  # owen
 #当这个闭包里只写了Owen,那就会一直使用owen
    
 def outer(username):
    def index():
        print(username)
    return index
res = outer('mary') # 形参username与值mary临时绑定到outer局部名称中
res()  # mary
res1 = outer('owen')# 形参username与值owen临时绑定到outer局部名称空间里面
res1()  # owen

# 想要修改参数,就重新定义一个值,进行重新绑定

三、装饰器简介

装饰器的本质:
    例如给函数index装饰
    在不改变index原有的'调用方式''内部代码'的情况下给index添加新的功能
    
装饰器的原则:
   """对外扩展开放,对修改封闭"""
import time(调用模块)
print(time.time())  # 1647589902.705415
# 获取的数字就是时间戳:1970年1月1日0时0分0秒距离刚刚代码运行间隔的秒数
time.sleep(3)  # 让程序原地休眠三秒
print('hello world')
print(time.time())
# hello world
# 1647590604.362981
  • 统一函数的执行时间
import time
def index():
    time.sleep(3)
    print('from index')
start_time = time.time()  # 函数执行之前获取的时间节戳
index()
end_time = time.time()  # 函数执行之后获取一个时间戳
print(end_time - start_time)  # 用第二个时间戳减第一个时间戳,结果就是函数的执行时间

四、简易版本装饰器

'''给index函数增加了一个统计执行时间的功能'''
def index():
    time.sleep(1)
    print('from index')
start_time = time.time()  # 函数执行之前获取一个时间戳
index()
end_time = time.time()  # 函数执行之后获取一个时间戳
print(end_time - start_time)  # 两个时间戳的差值就是函数的执行时间
# 这个只能给一个函数增加功能

import time
def index():
    time.sleep(1)
    print('from index')
def home():
    time.sleep(3)
    print('from home')
print(home)
def outer(func):
    def get_time():
        start_time = time.time()  # 函数执行之前获取一个时间戳
        func()  # 调用了真正的index函数
        end_time = time.time()  # 函数执行之后获取一个时间戳
        print(end_time - start_time)  # 两个时间戳的差值就是函数的执行时间
    return get_time
home = outer(home)  # 狸猫换太子
home()
print(home)

五、进阶版本装饰器

# 解决的是参数问题
def out (func_name):  
    def get_time(*args, **kwargs):
        start_time = time.time()  # 开始获取一个时间
        func_name(*args, **kwargs)
        end_time = time.time()  # 结束获取一个时间
        print(end_time - start_time)
    return get_time
# 这个主要可以改变参数,参数的类型都可以

六、完整版装饰器

# 解决的是返回值问题
import time
def index(username):
    time.sleep(3)
    return username
def outer(func_name):
    def get_time(*args, **kwargs):  # 可变长形参,什么数据类型都可以
        start_time = time.time()
        res = func_name(*args, **kwargs)  # 执行真正的index函数
        end_time = time.time()
        print(end_time - start_time)
        return res  # 返回原函数的值,没有的时候返回的是none
    return get_time
index = outer(index)
res = index('起飞')
print(res)

七、装饰器模板

# 兄弟们,这才是关键
def outer(func_name):  # func_name用于接收被装饰的对象(函数)
    def inner(*args, **kwargs):
        print('执行被装饰函数之前 可以做的额外操作')
        res = func_name(*args, **kwargs)  # 执行真正的被装饰函数
        print('执行被装饰函数之后 可以做的额外操作')
        return res  # 返回真正函数的返回值
    return inner

八、装饰器语法糖

# 语法糖内部原理
  1、使用时最好紧跟在被装饰对象上面
  2、语法糖会自动将下面紧挨着的函数名床给@后面的函数调用
# 先定义一个outer函数
def outer(func_name):
    def inner(*args, **kwargs):
        print('执行函数之前的操作')
        res = func_name(*args, **kwargs)
        # 额外操作
        return res
    return inner
#  使用outer直接@加outer
@outer  # 等价于 index = outer(index)
def index(*args, **kwargs):
    print('from index')
print(index)   


@outer  # 等价于 home = outer(home)
def home(*args,**kwargs):
    print('from home')
print(home)

九、装饰器修复技术

from functools import wraps  # 固定搭配
def outer(func_name):
    @wraps(func_name)  # wraps模块warps关键字可以把真函数的属性提取出来,赋值给装饰器,达到以假乱真的地步
    def inner(*args, **kwargs):
        print('执行被装饰对象之前可以做的操作')
        res = func_name(*args, **kwargs)
        return res
    return inner
@outer
def home():
    '''这是函数的注释'''
    print('from home')
home()
print(home)
help(home)
# 结果为
from home
<function home at 0x00000249C8FDFCA0>
Help on function home in module __main__:
posted @   未月  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示