函数装饰器


image

今日内容概要

  • 装饰器简易版本
  • 装饰器进阶版本
  • 装饰器练习
  • 装饰器固定模板
  • 装饰器语法糖(简化代码)
  • 有参装饰器

image

内容详细

装饰器简易版本
# eg: 给函数添加统计执行时间的功能

import time
#定义待计算运行时间的无参函数
def name():
    time.sleep(2)
    print('来打我呀')
#用装饰器添加时间计算功能
def func(res):
    def index():
        start_time = time.time()
        name()
        end_time = time.time()
        print('运行时间是:',end_time-start_time)
    return index  # 将index返回出去
res=func(name)  # 第二次res其实是=index
res()  # 此时相当于 index()

image

解决参数问题
import time
# 定义一个无参函数
def index():
    time.sleep(2)
    print('from index')

# 定义一个有参函数
def log(name):
    time.sleep(2)
    print('from log')

# 写时间计算装饰器
def otter(func):  # func = index    func = log
    def data(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        end_time = time.time()
        print('运行时间为:', end_time-start_time)
    return data
index = otter(index)  # index = data
index()  # data()
log = otter(log)  # log = data
log('jason')  # data() log函数体代码有参数 此处必须先传入实参才可以调用成功log函数体代码

image

解决返回值问题
import time
def index():
    time.sleep(3)
    print('亚洲最大的线上赌场开业了 日本女优在线发牌!!!')
    return 'from index'
def login(name):
    time.sleep(1)
    print('%s正在发牌'%name)
    return 'from login'
def outer(func):  # func指向的是函数名login
    # func = login
    def get_time(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)  # 接收被装饰函数的返回值
        end_time = time.time()
        print('函数运行时间:%s' % (end_time - start_time))
        return res  # 执行完get_time之后返回被装饰函数执行之后的返回值
    return get_time  # 将get_time函数名返回出去
# index = outer(index)
# res = index()
# print(res)
login = outer(login)
res1 = login('jason')
print(res1)

image

认证装饰器
import time
def index():
    time.sleep(1)
    print('百万大奖等你来拿 赶快加入我们吧!!!')
def home():
    time.sleep(1)
    print('学学学 一天到晚就是学 卷死你们这些家伙')
def register():
    time.sleep(1)
    print('注册功能')
    
# 给 index 函数增加认证功能
	调用index之前需要用户输入姓名和密码
	正确才可以调用
	错误则拒绝
    
# 定义一个用于记录用户是否登录的数据
is_login = {'is_login':False}


def login_auth(func):
    def auth(*args,**kwargs):
        # 1.1 先判断用户是否已经登录
        if is_login.get('is_login'):
            # 3.正常执行函数index
            res = func(*args, **kwargs)
            return res
        # 1.先获取用户的用户名和密码
        username = input('username>>>:').strip()
        password = input('password>>>:').strip()
        # 2.校验用户名和密码是否正确
        if username == 'jason' and password == '123':
            # 3.正常执行函数index
            res = func(*args,**kwargs)
            # 4.将记录用户登录状态的数据修改
            is_login['is_login'] = True
            return res
        else:
            print('用户名或密码错误 无法执行函数')
    return auth
index = login_auth(index)
index()
home = login_auth(home)
home()
register = login_auth(register)
register()

image

装饰器固定模板
def outer(func):
    def inner(*args, **kwargs):
        print('执行函数之前可以添加的额外功能')
        res = func(*args, **kwargs)  # 执行被装饰的函数
        print('执行函数之后可以添加的额外功能')
        return res  # 将被装饰函数执行之后的返回值返回
    return inner

image

装饰器语法糖
def outer(func):
    def inner(*args, **kwargs):
        print('执行函数之前可以添加的额外功能')
        res = func(*args, **kwargs)  # 执行被装饰的函数
        print('执行函数之后可以添加的额外功能')
        return res  # 将被装饰函数执行之后的返回值返回
    return inner
@outer  # 就相当于index = outer(index)
def index(*args, **kwargs):
    print('from index')
index()
@outer  # 就相当于home = outer(home)
def home():
    print('from home')
home()

"""
装饰器语法糖书写规范
	语法糖必须紧贴在被装饰对象的上方

装饰器语法糖内部原理
	会自动将下面紧贴着的被装饰对象名字当作参数传给装饰器函数调用
"""

image

双层语法糖
# 统计函数体代码运行时间
def get_time(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)  # 执行被装饰的函数
        end_time = time.time()
        print('函数执行时间:%s'%(end_time-start_time))
        return res  # 将被装饰函数执行之后的返回值返回
    return inner


# 校验用户登录装饰
def login_auth(func):
    def inner(*args, **kwargs):
        # 1.先获取用户的用户名和密码
        username = input('username>>>:').strip()
        password = input('password>>>:').strip()
        # 2.校验用户名和密码是否正确
        if username == 'jason' and password == '123':
            res = func(*args, **kwargs)  # 执行被装饰的函数
            return res  # 将被装饰函数执行之后的返回值返回
        print('用户名或密码错误 无权限执行')
    return inner
@login_auth  # 相当于index = login_auth(index)
@get_time  # 相当于index = get_time(index)
def index():
    time.sleep(1)
    print('from index')
index()

image

装饰器修复技术
from functools import wraps
def outer(func):
    @wraps(func)  # 修复技术就是为了让被装饰对象更加不容易被察觉装饰了  固定语法
    def inner(*args, **kwargs):
        print('执行函数之前可以添加的额外功能')
        res = func(*args, **kwargs)  # 执行被装饰的函数
        print('执行函数之后可以添加的额外功能')
        return res  # 将被装饰函数执行之后的返回值返回
    return inner

@outer  # index = outer(index)
def index():
    print('from index')
print(index)
help(index)

image

练习
# 判断七句print执行顺序
def outter1(func1):
    print('加载了outter1')
    def wrapper1(*args, **kwargs):
        print('执行了wrapper1')
        res1 = func1(*args, **kwargs)
        return res1
    return wrapper1

def outter2(func2):
    print('加载了outter2')
    def wrapper2(*args, **kwargs):
        print('执行了wrapper2')
        res2 = func2(*args, **kwargs)
        return res2
    return wrapper2

def outter3(func3):
    print('加载了outter3')
    def wrapper3(*args, **kwargs):
        print('执行了wrapper3')
        res3 = func3(*args, **kwargs)
        return res3
    return wrapper3


@outter1
@outter2
@outter3
def index():
    print('from index')
index()
"""
加载了outter3
加载了outter2
加载了outter1
执行了wrapper1
执行了wrapper2
执行了wrapper3
from index
"""

image

有参装饰器
def outer(source_data):
    # source_data = 'file'
    def login_auth(func):
        def auth(*args,**kwargs):
            # 2.校验用户名和密码是否正确
            # 数据的校验方式可以切换多种
            if source_data == 'file':
                # 从文件中获取用户数据并比对
                print('file文件获取')
            elif source_data == 'MySQL':
                # 从MySQL数据库中获取数据比对
                print('MySQL数据库获取')
            elif source_data == 'postgreSQL':
                # 从postgreSQL数据库中获取数据对比
                print('postgreSQL数据库获取')
            else:
                print('用户名或密码错误 无法执行函数')
        return auth
    return login_auth

@outer('file')  # @login_auth>>index=login_auth(index)>>auth
def index():
    print('from index')
@outer('MySQL')
def home():
    print('from home')

index()
home()

image

posted @ 2021-11-17 20:09  Deity_JGX  阅读(68)  评论(0)    收藏  举报