装饰器

闭包函数

1.闭:定义在函数内部的函数

2.包:内部函数使用了外层函数名称中的名字

def outer():  #外部函数
    x = 999
    def inner():   #内部函数:使用的是外层函数的返回值
        print('from outer>>>inner',x)
    return inner(外层函数的返回值)
x = 666
res = outer()   #相当于inner(因为打印res,就是返回值inner)
res()   #执行inner

闭包函数实际应用

函数体传参方式:

1.形参

def index(username):     #直接通过形参传
    print(username)  

index('jason')即可调用 

2.闭包

def outer(username):#为了让里面的名字都可以变,使用形参(由于已经使用了一个外包了,就不使用了)
    def index():
        print(username)
    return(index)
res = outer('jason') #这里的res就是index
res() #调用index函数

装饰器简介

装饰器不是新知识的,就是前几天学习的名称空间/函数名/闭包函数。。。的产物

本质:不改变越来的调用方式内部代码的情况下给装饰器添加新的功能

原则:对扩展开放,对修改封闭

小知识点:
①import time
print(time.time())  #1647568920.168808
'''上述的数字是时间戳:1970年1月1日0时0分0秒距离刚刚代码运行间隔的秒数'''

②time.sleep(3)  #让程序原地等待三秒
统一测量函数执行时间
import time
def index():
    time.sleep(3)
    print('from index')
'''现在给index增加一个统计执行时间的功能'''

 start_time = time.time() # 函数执行之前获取一个时间戳

index()
end_time = time.time() # 函数执行之后获取一个时间戳
print(end_time - start_time) # 两个时间戳的差值就是函数的执行

装饰器进化过程

简易版本 

在很多地方都需要执行统计index函数执行时间的代码
在不同的地方需要执行相同的代码 >>>: 函数

import time
def index():
    time.sleep(1)
    print('from index')


def outer(func):  # 真正的index被outer局部名称空间func存储了
    def get_time():
        start_time = time.time()  # 函数执行之前获取一个时间戳
        func()  # 调用了真正的index函数
        end_time = time.time()  # 函数执行之后获取一个时间戳
        print(end_time - start_time)  # 两个时间戳的差值就是函数的执行时间
    return get_time
index = outer(index)#右边调用outer函数,返回get_time,调用出get_time函数,测量函数index时间(这个时候的func就是index)
index
()#调用get_time函数
这里的左边的index是普通变量名,也可以是a(狸猫换太子,为了后面调用时候一样,其实这里左边的index是get_time)

进阶版本装饰器
# 解决的是参数问题
def outer(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
完整版本装饰器
# 解决的是返回值问题
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  #此时的res就是index函数,res的返回值就是index的返回值
    return get_time

装饰器模板!

'''编写装饰器其实有一套固定的代码 不需要做任何理解'''
def outer(func_name):  # func_name用于接收被装饰的对象(函数)
    def inner(*args, **kwargs):
        print('执行被装饰函数之前 可以做的额外操作')
        res = func_name(*args, **kwargs)  # 执行真正的被装饰函数
        print('执行被装饰函数之后 可以做的额外操作')
        return res  # 返回真正函数的返回值
    return inner

  装饰器语法糖

 #仅仅是让代码编写的更加好看、简洁!!!
def outer(func_name):
    def inner(*args, **kwargs):
        print('执行函数之前的操作')
        res = func_name(*args, **kwargs)
        # 额外操作
        return res
    return inner
index = outer(index)  #左边的index是outer函数的返回值inner(但是这一行太low了!)
index()  #相当于调用inner函数
print(index)  #打印inner函数的返回值res,而res的返回值就是index的返回值




以后这么写
@outer  # 等价于 index = outer(index)    #相当于装饰器直接装上了,方便!!
def index(*args, **kwargs):
    print('from index')


以后调用,直接用
index()
看返回值也直接用
print(index)

装饰器修复技术

防止有些人查看位置,看到位置改变,比如使用print打印函数位置,前后变化
用help去看指定函数的注释信息,eg help(home)  所有有瑕疵

#
# 做到比真的还要真 但是本质其实没有变 from functools import wraps def outer(func_name): @wraps(func_name) def inner(*args, **kwargs): print('执行被装饰对象之前可以做的操作') res = func_name(*args, **kwargs) return res return inner @outer def index(): print('from index')

 

posted @ 2023-07-16 09:15  半糖+奶茶  阅读(12)  评论(0)    收藏  举报