Python“三大器”之装饰器2

python

装饰器

1、叠加装饰器

(1)什么是叠加装饰器

  在同一个被装饰对象中,添加多个装饰器并执行

(2)为什么要使用叠加装饰器

  不使用叠加装饰器会导致代码冗余,结构不清晰,可扩展性差,所以最好每一个新的功能都应该写一个新的装饰器

(3)怎么使用叠加装饰器

  使用方式:

 

    @装饰1

    @装饰2

    @装饰3

    def 被装饰对象():

      pass

 

例子1:

  我的需求:为被装饰对象,添加统计与登录认证功能

import time

user_info = {

"user": None

}

# 登陆功能

def login():

username = input("请输入您的账户:").strip()

password = input("请输入您的密码:").strip()

with open("dir/passwd.txt", "r", encoding="utf-8") as f: # 我在同级目录下创建了一个dir目录,然后在目录下创建了一个passwd的文本文档,里面内容为tank:123,然后回车另起一行保存

info = f.readline().strip("

").split(":")

name, pwd = info

if username == name and password == pwd:

print("登陆成功...")

user_info["user"] = username

else:

print("登录失败...")

# 登录认证装饰器

def login_auth(func):

def inner1(*args, **kwargs):

# 登录认证功能

if user_info.get("user"):

res = func(*args, **kwargs)

return res

else:

login()

return func(*args, **kwargs) # 无论inner1中出现任何判断,最后都要返回“调用后的被装饰对象”:func(*args, **kwargs)

return inner1

##### 注意:登陆这里无论inner1中出现任何判断,最后都要返回“调用后的被装饰对象”:func(*args, **kwargs)

# 统计时间装饰器

def time_record(func):

def inner2(*args, **kwargs):

print("开始统计...")

start_time = time.time()

res = func(*args, **kwargs)

end_time = time.time()

print(f"消耗时间为{end_time - start_time}")

return res

return inner2

# 装饰顺序:先装饰time_record,再装饰login_auth

@login_auth # inner1 = login_auth(inner2)

@time_record # inner2 = time_record(download_movie)

def download_movie():

print("电影开始下载...")

time.sleep(3)

print("电影下载完成!")

return"gtwz.mp4"

# 执行顺序:先执行login_auth,再执行time_record

# 只统计下载电影的时间

login() # 先调用用户登录,模拟用户已登录

download_movie()

注意:装饰器在调用被装饰对象时才会执行添加的功能

  装饰的顺序:由下到上

  执行的顺序:由上到下

 

  附上图解:

 

例子2:通过例子看到执行过程:

def wrapper1(func1):

def inner1(*args, **kwargs):

print("1-----start")

# 被装饰对象在调用时,如果还有其他装饰器,会先执行其他装饰器中的inner

# 下一步执行inner2

res = func1(*args, **kwargs)

print("1-----end")

return res

return inner1

def wrapper2(func2):

def inner2(*args, **kwargs):

print("2-----start")

# 被装饰对象在调用时,如果还有其他装饰器,会先执行其他装饰器中的inner

# 下一步执行inner3

res = func2(*args, **kwargs)

print("2-----end")

return res

return inner2

def wrapper3(func3):

def inner3(*args, **kwargs):

print("3-----start")

# 被装饰对象在调用时,没有其他装饰器

# 下一步执行index

res = func3(*args, **kwargs)

print("3-----end")

return res

return inner3

@wrapper1 # inner1 = wrapper1(inner2)

@wrapper2 # inner2 = wrapper2(inner3)

@wrapper3 # inner3 = wrapper3(index)

# 被装饰对象

def index():

print("hello")

"""

装饰顺序:

从下到上

执行顺序:

从上到下

本例子的执行顺序:

inner1()

inner2()

inner3()

index()

inner3的res

inner2的res

inner1的res

"""

 

2、无参装饰器和有参装饰器

(1)无参装饰器

  在被装饰对象装饰时,没有传参数的装饰器


    @wrapper1
    @wrapper2
    @wrapper3


  无参装饰器模板:

# 无参装饰器模板:

def wrapper(func):

def inner(*args, **kwargs):

# 添加代码块功能

res = func(*args, **kwargs)

# 添加代码块功能

return res

return inner

(2)有参装饰器

  有参装饰器:在某些时候,需要给用户的权限进行分类

    @wrapper1(参数1)
    @wrapper2(参数2)
    @wrapper3(参数3)

  有参装饰器模板:

# 有参装饰器模板:

def outer(para): # 传入的para参数是用在inner()内部函数使用

def wrapper(func):

def inner(*args, **kwargs):

if para == "": # 功能1

# 添加调用前的功能代码块1

res = func(*args, **kwargs)

# 添加调用后的功能代码块1

return res

elif para == "": # 功能2

# 添加调用前的功能代码块2

res = func(*args, **kwargs)

# 添加调用后的功能代码块2

return res

else: # 功能3

# 添加调用前的功能代码块3

res = func(*args, **kwargs)

# 添加调用后的功能代码块3

return res

# 无论inner中出现任何判断,最后都要返回“调用后的被装饰对象”:func(*args, **kwargs)

return inner

return wrapper

例1:可通过传参查看用户权限/功能

def user_auth(user_role):

def wrapper(func):

def inner(*args, **kwargs):

if user_role == "SVIP":

# 添加svip的权限/功能

print(user_role)

res = func(*args, **kwargs)

return res

elif user_role == "VIP":

# 添加vip的权限/功能

print(user_role)

res = func(*args, **kwargs)

return res

return inner

return wrapper

@user_auth("VIP")

def index():

pass

index()

 

3、wraps修复(了解)

  wraps是一个修复工具,修复的是被装饰对象的空间

functools import wraps

def wrapper(func):

@wraps(func) # 修改名称空间:inner ---> func

def inner(*args, **kwargs):

"""

这里是装饰器

:param args:

:param kwargs:

:return:

"""

res = func(*args, **kwargs)

return res

return inner

def index():

"""

这里是被装饰对象

:return:

"""

pass

print(index)

print(index.__doc__)

以上是 Python“三大器”之装饰器2 的全部内容, 来源链接: utcz.com/z/530937.html

回到顶部