装饰器

装饰器

image

1.初级装饰器

# 定义一个函数index
import time
def index():
    time.sleep(1)
    print('这是被装饰的对象')
def home():
    print('这是一个别装饰的函数')
# 写一个装饰器可以计算函数index运行时间
# 定义一个函数可以调用时实现该功能
def outer(func):
# func = index
    def inner():
        # 获取函数运行前的时间
        start_time = time.time()
        # 调用函数
        func()
        # 获取函数运行结束后的时间
        end_time = time.time()
        # 打印函数运行的时间
        print(f'这是函数{func}的运行时间%s' %(end_time -start_time))
    return inner
index = outer(index)
index()
home = outer(home)
home()
'''该装饰器只能简单的实现index函数是无参函数的情况,
且如果该装饰器被多个函数调用时,只能通过在装饰器内部修改参数来实现
不能通过直接调用装饰器时传参来满足不同函数的需求'''

image

2.进阶装饰器

# 当被装饰对象里有参数,且有返回值的时候怎么解决
import time
def index(name):
    time.sleep(1)
    print('这是一个被装饰的对象%s'%name)
    return 'from index'
def home(age):
    time.sleep(1)
    print('这是一个被装饰的函数%s'%age)
# 统计函数运行时间装饰器
def outer(func):
    # func = index
    def inner(*args,**kwargs):
        # 获取被装饰对象函数运行之前的时间
        start_time = time.time()
        # 执行被装饰对象函数
        res =func(*args,**kwargs)
        # 获取被装饰对象函数运行之后的时间
        end_time = time.time()
        print(f'{end_time - start_time}')
        return res
    return inner
# index = outer(index)
# res = index('jason')
# print(res)
home = outer(home)
home(18)

image

3.认证程序装饰器

def index(name):
    print(f'性感荷官{name}在线发牌')
    return '欢迎下次再来!'
def home(name):
    print(f'大唐洗浴中心欢迎你,由{name}为您服务')
    return '欢迎下次再来'

# 定义一个字典,用来判断用户的登录状态
is_login = {'is_login':False}
def outer(func):
    def inner(*args,**kwargs):
        # 判断用户的登录状态
        if is_login.get('is_login'):
            res = func(*args,**kwargs)
            return res
        # 获取用户的输入
        user_name = input('输入你的登录名:').strip()
        password = input('输入你的密码:').strip()
        # 根据用户的输入进行比对
        if user_name == 'jason' and password == '123':
            # 如果成功了则调用函数并获取函数的返回值
            res = func(*args,**kwargs)
            # 用户登录成功,则修改登录的状态,不要再频繁登录
            is_login['is_login'] = True
            return res
        print('登录名或者密码输入错误,请重新输入')
        return '下次再来'
    return inner

index = outer(index)
res = index('jason')
print(res)
home = outer(home)
res1 = home('jason')
print(res1)

image

4.装饰器修复技术

# 何为装饰器修复技术
当我们使用装饰器装饰某对象时,虽然调用时,形式上看是和被装饰对象的函数名一样,
实际上,只是用一个和被装饰对象函数名相同的变量名指向,可以在不改变原来函数的内部代码和调用方式的
情况下执行原函数,而在调用时执行的函数本身并不是原函数,所以可以用装饰器修复技术,使得我们的装饰器更加的完美
from functools import wraps
import time
# 统计函数运行时间装饰器
def get_time(func):
    # func = index
    @wraps(func)  # 修复技术就是为了让被装饰对象更加不容易被察觉装饰了
    def inner1(*args,**kwargs):
        # 获取被装饰对象函数运行之前的时间
        start_time = time.time()
        # 执行被装饰对象函数
        res =func(*args,**kwargs)
        # 获取被装饰对象函数运行之后的时间
        end_time = time.time()
        print(f'{end_time - start_time}')
        return res
    return inner1

is_login = {'is_login':False}
def login(func):
    @wraps(func)  # 修复技术就是为了让被装饰对象更加不容易被察觉装饰了
    def inner2(*args,**kwargs):
        # 判断用户的登录状态
        if is_login.get('is_login'):
            res = func(*args,**kwargs)
            return res
        # 获取用户的输入
        user_name = input('输入你的登录名:').strip()
        password = input('输入你的密码:').strip()
        # 根据用户的输入进行比对
        if user_name == 'jason' and password == '123':
            # 如果成功了则调用函数并获取函数的返回值
            res = func(*args,**kwargs)
            # 用户登录成功,则修改登录的状态,不要再频繁登录
            is_login['is_login'] = True
            return res
        print('登录名或者密码输入错误,请重新输入')
        return '下次再来'
    return inner2
@login #  login(get_time(index)) = inner2 # index = inner2  # index() = inner2()
@get_time  # get_time(index) = inner1
def index(name):
    print(f'性感荷官{name}在线发牌')
    return '欢迎下次再来!'
res = index('jason')
print(res)
print(index)  # <function index at 0x000001A2CA1F80D8>

5.装饰器固定模板

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

    return inner


'''调用时:
被装饰对象函数名绑定的变量名 = 装饰器函数名(被装饰对象函数名)
res = 被装饰对象函数名绑定的变量名()# 获取被装饰对象的返回值
print(res)
'''

image

6.装饰器语法糖

# 装饰器语法糖是为了在调用装饰器时可以简化代码
# 语法结构:@+装饰器函数名
# 定义一个字典,用来判断用户的登录状态
is_login = {'is_login':False}
def outer(func):
    def inner(*args,**kwargs):
        # 判断用户的登录状态
        if is_login.get('is_login'):
            res = func(*args,**kwargs)
            return res
        # 获取用户的输入
        user_name = input('输入你的登录名:').strip()
        password = input('输入你的密码:').strip()
        # 根据用户的输入进行比对
        if user_name == 'jason' and password == '123':
            # 如果成功了则调用函数并获取函数的返回值
            res = func(*args,**kwargs)
            # 用户登录成功,则修改登录的状态,不要再频繁登录
            is_login['is_login'] = True
            return res
        print('登录名或者密码输入错误,请重新输入')
        return '下次再来'
    return inner

@outer  # index = outer(index)
def index(name):
    print(f'性感荷官{name}在线发牌')
    return '欢迎下次再来!'
index('jason')
@outer  # home = outer(home)
def home(name):
    print(f'大唐洗浴中心欢迎你,由{name}为您服务')
    return '欢迎下次再来'
home('jason')
'''装饰器语法糖必须紧贴在被装饰对象的上面
装饰器语法糖的内部原理
    会将紧贴在装饰器语法糖下面的函数名作为参数传递给装饰器函数
'''

image

7.双层装饰器语法糖

import time
# 统计函数运行时间装饰器
def get_time(func):
    # func = index
    print('欢迎')
    def inner1(*args,**kwargs):
        # 获取被装饰对象函数运行之前的时间
        start_time = time.time()
        # 执行被装饰对象函数
        res =func(*args,**kwargs)
        # 获取被装饰对象函数运行之后的时间
        end_time = time.time()
        print(f'{end_time - start_time}')
        return res
    return inner1

is_login = {'is_login':False}
def login(func):
    print('光临')
    def inner2(*args,**kwargs):
        # 判断用户的登录状态
        if is_login.get('is_login'):
            res = func(*args,**kwargs)
            return res
        # 获取用户的输入
        user_name = input('输入你的登录名:').strip()
        password = input('输入你的密码:').strip()
        # 根据用户的输入进行比对
        if user_name == 'jason' and password == '123':
            # 如果成功了则调用函数并获取函数的返回值
            res = func(*args,**kwargs)
            # 用户登录成功,则修改登录的状态,不要再频繁登录
            is_login['is_login'] = True
            return res
        print('登录名或者密码输入错误,请重新输入')
        return '下次再来'
    return inner2
@login #  login(get_time(index)) = inner2 # index = inner2  # index() = inner2()
@get_time  # get_time(index) = inner1
def index(name):
    print(f'性感荷官{name}在线发牌')
    return '欢迎下次再来!'
res = index('jason')
print(res)
print(index)  # <function login.<locals>.inner2 at 0x0000029AA02A8168>

'''当出现多个装饰器语法糖连用时,先从和装饰器紧贴着的函数开始
    由下往上依次调用,当最后一个装饰器语法糖上面不再有语法糖的时候,
    用一个和被装饰对象名字相同的变量名接受装饰器的返回值
'''

image

8.有参装饰器

import time
# 统计函数运行时间装饰器
def get_time(func):
    # func = index
    print('欢迎')
    def inner1(*args,**kwargs):
        # 获取被装饰对象函数运行之前的时间
        start_time = time.time()
        # 执行被装饰对象函数
        res =func(*args,**kwargs)
        # 获取被装饰对象函数运行之后的时间
        end_time = time.time()
        print(f'{end_time - start_time}')
        return res
    return inner1

is_login = {'is_login':False}
def login(func):
    print('光临')
    def inner2(*args,**kwargs):
        # 判断用户的登录状态
        if is_login.get('is_login'):
            res = func(*args,**kwargs)
            return res
        # 获取用户的输入
        user_name = input('输入你的登录名:').strip()
        password = input('输入你的密码:').strip()
        # 根据用户的输入进行比对
        if user_name == 'jason' and password == '123':
            # 如果成功了则调用函数并获取函数的返回值
            res = func(*args,**kwargs)
            # 用户登录成功,则修改登录的状态,不要再频繁登录
            is_login['is_login'] = True
            return res
        print('登录名或者密码输入错误,请重新输入')
        return '下次再来'
    return inner2
@login #  login(get_time(index)) = inner2 # index = inner2  # index() = inner2()
@get_time  # get_time(index) = inner1
def index(name):
    print(f'性感荷官{name}在线发牌')
    return '欢迎下次再来!'
res = index('jason')
print(res)
print(index)  # <function login.<locals>.inner2 at 0x0000029AA02A8168>

'''当出现多个装饰器语法糖连用时,先从和装饰器紧贴着的函数开始
    由下往上依次调用,当最后一个装饰器语法糖上面不再有语法糖的时候,
    用一个和被装饰对象名字相同的变量名接受装饰器的返回值
'''

image

posted @ 2021-11-17 20:05  PyLy  阅读(79)  评论(0)    收藏  举报

念两句诗

入我相思门,知我相思苦,长相思兮长相忆,短相思兮无穷极。
【唐代】李白