核心主题:装饰器

装饰器的概念

"""
装饰器它不是一个新的知识点,它是有之前我们学习的名称空间、函数嵌套、闭包函数等知识点汇总而来
"""
​
什么是装饰器:
    器:指工具
    装饰:添加功能
    
装饰器的核心思想:
    在'不改变原来的调用方式'和'内部代码'的基础之上给函数'添加额外的功能'.
    
def index():
    pass
​
index()
​
# 给index函数添加统计执行时间的功能.
补充:如何计算时间
import time
​
import time # 内置的时间模块,拿来直接用
​
print(time.time()) # 1694139138.4503667 称为是时间戳:1694139138秒数,从1970-1-1到当前时间的秒数
​
# 1694139138.4503667-------------》格式化之后的时间
​
time.sleep(3) # 睡眠
print(123)
​
def index():
    time.sleep(3)
    print('from index')
​
​
# 1. 在执行函数之前加一个时间点
start_time = time.time() # 此时的时间戳
index()
​
# 2. 等index函数执行之后在打个时间点
end_time = time.time()
​
# 3. 获取index 的总执行时间
print('index一共执行了%s秒' % (end_time - start_time))

装饰器的简易版本

import time
​
​
def index():
    time.sleep(3)
    print('from index')
​
​
def home():
    time.sleep(1)
    print('from home')
​
​
def outer(func):
    # func:index
    # func = home
    def get_time():
        # func:index
        start_time = time.time()
        # index() # 只能够统计index函数的时间
        # func()---->index()
        func()  # 只能够统计index函数的时间
        end_time = time.time()
        print('执行时间:%s' % (end_time - start_time))
​
    return get_time
​
​
# get_time(index()) # get_time(None)
# get_time(index) #
​
index = outer(index)  # res:get_time的函数名(其实也是get_time的内存地址)
index()  # get_time()
# res = outer(home)
# res()

装饰器进阶版本(解决参数问题、解决返回值问题)

import time
​
​
def index():
    time.sleep(3)
    print('from index')
​
​
def home(name):
    time.sleep(1)
    print('from home:', name)
​
​
def outer(func):
    # func:index
    # func = home
    def get_time(*args, **kwargs):
        # func:index
        start_time = time.time()
        # index() # 只能够统计index函数的时间
        # func()---->index()
        # func:home
        func(*args, **kwargs)  # 只能够统计index函数的时间
        end_time = time.time()
        print('执行时间:%s' % (end_time - start_time))
​
    return get_time
​
​
# get_time(index()) # get_time(None)
# get_time(index) #
​
index = outer(index)  # res:get_time的函数名(其实也是get_time的内存地址)
index('aaa')  # get_time()
# home = outer(home)
# home('jerry')  # get_time('jerry')
​
'''
我们现在统计的函数有时候需要参数,有时候不需要参数,所以,参数到底应该传还是不传?
    我们确定不了什么时候传,或者是传几个?
        如何将解决?
            *args和**kwargs
            
'''

解决返回值问题

def outer(func):
    # func:index
    # func = home
    def get_time(*args, **kwargs):
        # func:index
        start_time = time.time()
        # index() # 只能够统计index函数的时间
        # func()---->index()
        # func:home
        res=func(*args, **kwargs)  # 只能够统计index函数的时间
        end_time = time.time()
        print('执行时间:%s' % (end_time - start_time))
        # return res # 其实返回的是上面index的返回值
        return res
    return get_time
​
home = outer(home)
res=home('jerry')  # get_time('jerry')
print(res)

装饰器练习题(认证登录功能)

# 必须登录之后才能够访问函数
def index():
    print('from index')
​
​
def home():
    print('from home')
​
def home1():
    print('from home1')
​
# index()
# 用户必须是登录之后才能访问,否则不让访问
​
is_login={'is_login':False}
​
# 1. 写一个登录程序
def outer(func):
    # func = index
    def auth():
        if is_login.get('is_login'):
            ## 如果条件成立,直接执行函数
            res=func()
            return res # 解决返回值问题的
​
        username = input('username:>>>').strip()
        password = input('password:>>>').strip()
​
        # 2. 比较用户名和密码
        if username == 'jerry' and password == '123':
            # 执行函数
            print('登录成功')
            func()
            is_login['is_login'] = True #
        else:
            print('用户名或者密码错误')
    return auth
​
# auth(index)
# auth(home)
​
index=outer(index)
index()
​
home=outer(home)
home()
​
home1=outer(home1)
home1()
​
"""
我们现在需要做:只要登录成功一次,后续的函数就不用在登录了,直接可以访问?
"""

装饰器的固定模板

def outer(func):
    def inner(*args, **kwargs):
        print('函数被调用之前需要添加的功能')
        res=func(*args, **kwargs) # 真正的函数执行
        print('函数被调用之后需要添加的功能')
        return res
​
    return inner
​
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')
#     return 'index'
# 
# 
# @outer # home=outer(home)
# def home():
#     print('from home')
# 
# # index = outer(index)
# 
# index()
# 
# home() # inner()
​
@outer # func=outer(func)
def func():
    print('from func')
    
func()
​

"""
1. 语法糖的书写规范:
   @装饰器名字
   必须把上面的写在被装饰对象的头上(紧贴着被装饰对象写)
   
2. 语法糖的原理:
   它会把下面的被装饰对象的名字当成参数传递给装饰器
"""


双层语法糖

import time


def outer(func):
    def get_time(*args, **kwargs):
        start_time = time.time()
        res = func(*args, **kwargs)  # 只能够统计index函数的时间
        end_time = time.time()
        print('执行时间:%s' % (end_time - start_time))
        return res

    return get_time

def login_auth(func):
    # func = index
    def auth():
        username = input('username:>>>').strip()
        password = input('password:>>>').strip()
        # 2. 比较用户名和密码
        if username == 'jerry' and password == '123':
            # 执行函数
            print('登录成功')
            func()
        else:
            print('用户名或者密码错误')
    return auth

@login_auth # index=login_auth(get_time) # index=auth
@outer      # get_time=outer(index)
def index():
    time.sleep(3)
    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')
index()

多层语法糖的练习题

import time

from functools import wraps
def outer(func):
    @wraps(func) # 修复技术
    def get_time():
        start_time = time.time()
        func()  # 只能够统计index函数的时间
        end_time = time.time()
        print('执行时间:%s' % (end_time - start_time))
    return get_time
 

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

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

'''修复技术就是为了让装饰器伪装的更像'''
# index()
# print(index) # <function index at 0x000002F69849A940>
# print(index) # <function index at 0x000002F69849A940>
# help(index)


@outer
def home():
    '''这是home函数'''

help(home)

有参装饰器(最难的)


def outter(source_type, *args1, **kwargs1):
    def login_auth(func):  # 参数个数只能有一个
        def auth(*args, **kwargs): #
            username = input('username:>>>').strip()
            password = input('password:>>>').strip()
            # 2. 比较用户名和密码
            """
                1. 文件中获取用户名和密码
                2. 从MySQL中获取用户名和密码
                3. 从oracle中获取用户名和密码
                4. 从postgresql中获取用户名和密码
            """
            if source_type == 'file':
                print('文件中获取用户名和密码')
            elif source_type == 'mysql':
                print('从MySQL中获取用户名和密码')
            elif source_type == 'oracle':
                print('从oracle中获取用户名和密码')
            elif source_type == 'postgresql':
                print('从postgresql中获取用户名和密码')

            if username == 'jerry' and password == '123':
                # 执行函数
                print('登录成功')
                func(source_type, *args, **kwargs)
            else:
                print('用户名或者密码错误')
        return auth
    return login_auth

@outter('file', 1, 2, 3, 4, 5, 6,)
def home():
    pass

home('mysql')

练习

1.请实现一个装饰器,把函数的返回值+100然后返回
def wapper(func):
    def innner(*args,**kwargs):
        ret=func(*args,**kwargs)
        ret=print(ret+100)
        return ret
    return innner
@wapper
def func(number):
    return int(number)
func(100)
2.请实现一个装饰器,通过一次调用使函数重复执行5次
ef wapper(func):
    def innner(*args,**kwargs):
        count=0
        while count<5:
            func(*args,**kwargs)
            count+=1
    return innner
@wapper
def func():
    print("执行")
func()
3.请实现一个装饰器每次调用函数时,将函数名字写入文件中
import time
def wapper(func):
    def inner(*args,**kwargs):
        with open("log",encoding="utf-8",mode="a+") as f:
            structime=time.localtime()
            f.write(f'北京时间:{time.strftime("%Y-%m-%d %H:%M:%S",structime)} 函数名字为:{func.__name__}\n')
        ret=func(*args,**kwargs)
        return ret
    return inner
@wapper
def func():
    print("执行")
func()

posted @ 2023-09-11 19:45  橙子先生呀  阅读(4)  评论(0编辑  收藏  举报  来源