python基础day14 装饰器详情

发布时间 2023-05-30 14:57:11作者: 追逐的小白

装饰器的建议版本

核心思想:

  在不改变被装饰对象内部代码和原有调用方式的基础之上添加额外的功能

# 给index函数添加统计执行时间的功能
def index():
    time.sleep(3)
index()

import time


def index():
    time.sleep(3)
    print('from index')


def home():
    time.sleep(2)
    print('from home')


def func():
    time.sleep(2)
    print('from home')


def outer(func):
    # func = index
    def get_time():
        # func:index
        # 1. 在函数执行之前打一个时间点
        start_time = time.time()
        func()  # index()
        # 2. 在函数执行完毕之后在打一个时间点
        end_time = time.time()

        # 3. 两个时间的差值就是函数的实际执行时间
        print("函数执行了:%s秒" % (end_time - start_time))

    return get_time


# 利用闭包的形式来传参
# res = outer(index)  # res:get_time的内存地址
# res()  # get_time()

home = outer(home)
home()

解决参数的问题

def index(name, username):
    time.sleep(3)
    print('from index')


def home(name):
    time.sleep(2)
    print('from home', name)


def outer(func):
    # func = index
    def get_time(*args, **kwargs):
        # func:index
        # 1. 在函数执行之前打一个时间点
        start_time = time.time()
        func(*args, **kwargs)  # index()  func('tony')
        # 2. 在函数执行完毕之后在打一个时间点
        end_time = time.time()

        # 3. 两个时间的差值就是函数的实际执行时间
        print("函数执行了:%s秒" % (end_time - start_time))

    return get_time
index = outer(index)
index('tony', username='tank')

解决返回值问题

def home(name):
    time.sleep(2)
    print('from home', name)

def index():
    time.sleep(3)
    print('from index')
    return 'from index'

def outer(func):
    # func = index
    def get_time(*args, **kwargs):
        # func:index
        # 1. 在函数执行之前打一个时间点
        start_time = time.time()
        res=func(*args, **kwargs)  # index()  func('tony')
        # 2. 在函数执行完毕之后在打一个时间点
        end_time = time.time()

        # 3. 两个时间的差值就是函数的实际执行时间
        print("函数执行了:%s秒" % (end_time - start_time))
        return res
    return get_time
index = outer(index)
res=index()
print(res)

课堂练习(登录认证功能)

def home(name):
    print('from home')

def func():
    print('from func')
"""
    必须登录之后才能执行index函数
        如果不登录不让执行
"""
def login_auth(func):
    # func = index
    def auth(*args, **kwargs):
        # 写登录功能
        # 1.
        username = input('username:').strip()
        password = input('password:').strip()

        # 2. 验证用户名和密码是否正确
        if username == 'kevin' and password == '123':
            print('登录成功')
            res=func(*args, **kwargs)
            return res
        else:
            print('用户名或者密码错误')
    return auth

home=login_auth(home)
home('kevin')

装饰器模板

def outer(func):
    def inner(*args, **kwargs):
        print('这个是函数执行之前可以添加的功能')
        res = func(*args, **kwargs)
        print('这个是函数执行之后可以添加的功能')
        return res

    return inner


def index():
    print('from index')


index = outer(index)
index()

装饰器的语法糖

def outer(func):
    def inner(*args, **kwargs):
        print('这个是函数执行之前可以添加的功能')
        res = func(*args, **kwargs)
        print('这个是函数执行之后可以添加的功能')
        return res

    return inner


"""装饰器本质就是函数,函数就是功能"""
# 语法糖
@outer  # index = outer(index)
def index():
    print('from index')

@outer  # home=outer(home)  -----------> home是outer函数的返回值(内部函数的函数名)
def home():
    print('from home')

home() # inner()
# index = outer(index)
index()

# home = outer(home)
# home()
"""
语法糖的书写规范:
    紧贴着被装饰对象的上方写
语法糖的内部原理:
    他会自定把被装饰对象的名字当成参数传给装饰器函数调用
"""
@outer  # func = outer(func)
def func():
    print('from func')
    
func()  # inner()

 

双层语法糖

def login_auth(func):
    # func = index
    def auth(*args, **kwargs):
        # 写登录功能
        # 1.
        username = input('username:').strip()
        password = input('password:').strip()

        # 2. 验证用户名和密码是否正确
        if username == 'kevin' and password == '123':
            print('登录成功')
            res = func(*args, **kwargs)
            return res
        else:
            print('用户名或者密码错误')

    return auth


def get_time(func):
    # func = index
    def inner(*args, **kwargs):
        # func:index
        # 1. 在函数执行之前打一个时间点
        start_time = time.time()
        res = func(*args, **kwargs)  # index()  func('tony')
        # 2. 在函数执行完毕之后在打一个时间点
        end_time = time.time()

        # 3. 两个时间的差值就是函数的实际执行时间
        print("函数执行了:%s秒" % (end_time - start_time))
        return res

    return inner


@login_auth  # index=login_auth(get_time内部的inner函数名)
@get_time  # get_time内部的inner函数名=get_time(index)
def index():
    time.sleep(2)
    print('from index')

index()  # auth()

多语法糖练习题

# 判断七句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')

多认证登录功能

def login_auth(func):
    # func = index
    def auth(*args, **kwargs):
        # 判断用户是否登录了
        if is_login.get('is_login'):
            # 正常执行函数
            res = func(*args, **kwargs)
            return res
        # 写登录功能
        # 1.
        username = input('username:').strip()
        password = input('password:').strip()

        # 2. 验证用户名和密码是否正确
        if username == 'kevin' and password == '123':
            print('登录成功')
            res = func(*args, **kwargs)
            is_login['is_login'] = True
            return res
        else:
            print('用户名或者密码错误')

    return auth


@login_auth
def index():
    print('from index')


@login_auth
def home():
    print('from home')


index()
home()

装饰器的修复技术(了解)

from functools import wraps

def outer(func):
    # func = index
    @wraps(func)
    def get_time(*args, **kwargs):
        # func:index
        # 1. 在函数执行之前打一个时间点
        start_time = time.time()
        res = func(*args, **kwargs)  # index()  func('tony')
        # 2. 在函数执行完毕之后在打一个时间点
        end_time = time.time()

        # 3. 两个时间的差值就是函数的实际执行时间
        print("函数执行了:%s秒" % (end_time - start_time))
        return res

    return get_time

有参装饰器

# 有参装饰器就是带参数的装饰器
# 先前我们学习的装饰器就是无参装饰器:不到参数的装饰器

def outter(type):
    # type = 1
    def login_auth(func):
        # func = index
        def auth(*args, **kwargs):
            # 写登录功能
            # 1.
            username = input('username:').strip()
            password = input('password:').strip()

            # 2. 验证用户名和密码是否正确
            # with open('')
            """
                根据不同的参数用户名和密码来自于不同的位置
            """
            if type == 'file':
                print('用户名和密码来自于文件')
            elif type == 'mysql':
                print('用户名和密码来自于MySQL')
            elif type == 'oracle':
                print('用户名和密码来自于Oracle')

            # if username == 'kevin' and password == '123':
            #     print('登录成功')
            #     res = func(*args, **kwargs)
            #     return res
            # else:
            #     print('用户名或者密码错误')

        return auth
    return login_auth
# @login_auth  # 如果是index函数认证,用户名和密码来自于文件  login_auth(index, 1)
@outter('file') # @login_auth     # 如果是index函数认证,用户名和密码来自于文件  login_auth(index, 1)
def index():
    print('from index')

index()

# @login_auth  # 如果是home函数认证,用户名和密码来MySQL
@outter('mysql')  # 如果是home函数认证,用户名和密码来MySQL
def home():
    print('from home')

home()

@outter('oracle')  # 如果是func函数认证,用户名和密码来oracle
def func():
    print('from func')

func()