Skip to content

装饰器

  • 装饰器是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。

原型

python
# 把函数当做一个参数传入另一个函数
def func1(func):
    print('func1')
    func()

# 定义一个函数
def func2():
    print('func2')

# 调用func1函数 同时会执行func2函数
func1(func2)

升级版

python
# 定义一个装饰器
def decorator(fn):
    def wrapper():
        print('start')
        fn ()
        print('end')
    return wrapper

# 会把func1函数当做参数传入decorator函数
@decorator
def func1():
    print("func1")

# 调用func1函数 会先执行decorator函数 再执行func1函数
func1()  # start func1 end

最终版本

python
# 定义一个装饰器
def decorator(fn):
    def wrapper(*args,**kwargs):
        print('start')
        ret = fn(*args,**kwargs)
        print('end')
        return ret
    return wrapper

# 会把func1函数当做参数传入decorator函数
@decorator
def func1(x):
    print(x)

# 调用func1函数 会先执行decorator函数 再执行func1函数
func1("func1")  # start func1 end

多个装饰器

  • 执行顺序
    • 从下往上执行
    • 从里往外执行
python
def wrapper1(fn):
	def inner(*kargs, **kwargs):
		print("before wrapper1")
		ret = fn(*kargs, **kwargs)
		print("after wrapper1")
		return ret

	return inner


def wrapper2(fn):
	def inner(*kargs, **kwargs):
		print("before wrapper2")
		ret = fn(*kargs, **kwargs)
		print("after wrapper2")
		return ret

	return inner


@wrapper2 # target=wrapper2(wrapper1.inner) => wrapper2.inner
@wrapper1 # target=wrapper1(target) => wrapper1.inner
def target():
	print("target")

target()

输出结果

before wrapper2

before wrapper1

target

after wrapper1

after wrapper2

使用场景

  • 登录时
    • 登录验证
    • 权限验证
    • 记录日志
python
def login_check(fn):
    def wrapper(*args,**kwargs):
        # 登录验证
        username = input("请输入用户名:")
        password = input("请输入密码:")
        if username == "admin" and password == "123":
            print("登录成功")
        else:
            raise Exception("用户名或密码错误")
        # 权限验证
        if username == "admin":
            ret = fn (*args,**kwargs)
        else:
            raise Exception("您没有权限")
        # 记录日志
        # 关闭链接(数据库、文件等)
        return ret
    return wrapper

@login_check
def add():
    print("添加信息")

add()