其他分享
首页 > 其他分享> > 装饰器

装饰器

作者:互联网

闭包函数

1.特征
闭:定义在函数的内部的函数
包:内部函数使用了外层函数数名空间中的名字
def outer():
    x = 99
    def inner():
        print('from outer>>>inner',x)
        
    return inner
x = 66
res =outer()
res()

闭包函数实际应用

# 闭包函数是给函数体传参的另外一种方式
1.形参
def index(username):
    print(username)
# 函数体代码需要什么就可以在形参中写什么 
index('jason')

2.闭包
def outer(username):
    username = 'jason'
    def index():
        print(username)
    return index
res = outer('kevin')  # 形参username与值kevin临时绑定 >>>:outer局部名称空间中
res()
res1 = outer('jason')  # 形参username与值kevin临时绑定 >>>:outer局部名称空间中
res1()

装饰器简介

"""
装饰器并不是一个新的知识点 而是由前两天所有集合产物
	名称空间 函数名 闭包函数
"""
装饰器的本质
	在不改变被装饰对象原有的'调用方式'和'内部代码'
  的情况下给被装饰对象添加新的功能
装饰器的原则
	对扩展开放
  对修改封闭
import time
print(time.time())  # 1970年1月1日0:00开始到现在的秒数
time.sleep(3)  # 让程序原地等待三秒
print('hello world')

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)  # 两个时间戳的差值就是函数的执行时间

'''
1.思考:如果在很多地方都需要调用index 如何统计index执行时间
    在很多地方都需要执行统计index函数执行时间的代码
        在不同的地方需要执行相同的代码      >>>:       函数
    
    直接通过传参的方式
    缺陷1:
        代码写死了 无法统计其他函数的执行时间
        能否解决?
            可以!  将函数名通过形参的形式传入
    缺陷2:
        封装成函数之后 调用方式改变了 不符合装饰器原则
        能否解决?
            不可以
'''
# def get_time(func):
#     start_time = time.time()  # 函数执行之前获取一个时间戳
#     func()
#     end_time = time.time()  # 函数执行之后获取一个时间戳
#     print(end_time - start_time)  # 两个时间戳的差值就是函数的执行时间
# def home():
#     time.sleep(3)
#     print('from home')
# get_time(index)
# get_time(home)

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

进阶版本装饰器

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 '不要急躁' # 如何在此处返回真正index函数的返回值
        return res
    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

@outer  # 等价于 index = outer(index)
def index(*args, **kwargs):
    print('from index')
# index = outer(index)  # 总感觉这一行代码有点low!!!

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


print(index)
print(home)

"""
语法糖内部原理
    1.使用的时候最好紧跟在被装饰对象的上方
    2.语法糖会自动将下面紧挨着的函数名传给@后面的函数调用

ps:针对之前的周末大作业 只需要单独写一个装饰器 之后使用语法糖装饰即可
"""

标签:index,outer,函数,time,print,装饰,def
来源: https://www.cnblogs.com/wcc98/p/16022977.html