代码改变世界

Python装饰器

2022-01-18 11:47  何小六soso  阅读(25)  评论(0编辑  收藏  举报

Python装饰器

在不变原有代码,且保持函数调用方不变的情况下,给原函数增加新的功能

原理:用一个函数/类,去装饰一个函数/类,生成一个新的函数/类

语法:在原有的函数上增加@符号,装饰器会把下面的函数当做参数传递装饰器中,@符为语法糖

场景:引入日志,函数执行时间的统计,执行函数前、后的工作,权限校验,缓存等场景

​ 装饰器原型:闭包

​ 利用闭包,把函数当做参数传递,并且在内函数调用传递进来的函数,并返回内函数

def outer(f):  # 外函数
    def inner():  # 内函数
        f()

    return inner()  # 返回内函数

装饰器语法:

def outer(f):  # 外函数
    def inner():  # 内函数
        print('我是外函数中的内函数11111')
        f()
        print('我是外函数中的内函数22222')
    return inner  # 返回内函数

# def old():
#     print('我是一个老函数')
# outer(old)
'''
我是外函数中的内函数11111
我是一个老函数
我是外函数中的内函数22222
'''
#使用装饰器方法
@outer
def new():
    print('我是一个新函数,使用装饰器调用')
new()
'''
我是外函数中的内函数11111
我是一个新函数,使用装饰器调用
我是外函数中的内函数22222
'''

装饰器的应用:统计函数执行时间

# 普通装饰器
def outer(f):
    def inner():
        print('准备学习。。。。1')
        f()
        print('学习完成。。。。2')

    return inner

def two(f):
    def inner():
        print('第2层包裹。。。。3')
        f()
        print('第二层包裹。。。。4')
    return inner
# 扩展装饰器
def kuozhan(f):
    def inner():
        print('扩展1。。。。5')
        f()
        print('扩展2。。。。6')

    return inner


@kuozhan # 最外一层的包裹
@two
@outer #第一层包裹
def love():
    print('学习python。。。。7')


love()
'''
执行顺序:5-3-1-7-2-4-6
outer-->two-->kouzhan,代码运行时逐层包裹
'''

多参数函数语法:

# 多参数装饰器
import time


def outer(f):
    def inner(who, name, *args, **kwargs):
        print('多参数迭代器开始执行')
        f(who, name, *args, **kwargs)
        print('多参数迭代器执行完毕')
    return inner

# 定义多参数函数
@outer
def love(who, name, *args, **kwargs):
    print(f'{who}教{name}学习python')
    print(f'{who}教{name}学习', args)
    print(f'{who}教{name}看书', kwargs)

love('王老师','王同学','java','PHP',book='C')

带参数装饰器语法:

# 带参数的装饰器,如果装饰器需要参数,那么当前装饰器需要套个壳,用于接收装饰器的参数
def kuozhan(var):
    def outer(f):
        def inner1():
            print('做饭')
            f()
            print('吃饭')

        def inner():
            print(f'开始学习{var}')
            f()
            print('学习完成')

        if var == 'python':
            return inner
        else:
            return inner1

    return outer


@kuozhan('java')
def love():
    print('休息一下。。。。')


love()

类装饰器装饰函数语法:

# 类装饰器

class Outer():
    def __call__(self, fun): # 魔术函数
        self.fun = fun
        return self.inner

    def inner(self, name):
        print('装饰器开始')
        self.fun(name)
        print('装饰器结束')

@Outer()
def love(name):
    print(f'{name}学习python')
love('明明')

函数装饰器装饰类:

使用装饰器给类装饰,在类上方添加@装饰器对类进行装饰

装饰器给函数装饰,目的是不改变函数调用和代码的情况下给原函数增加了新的功能

装饰器给类装饰,目的是不改变类调用和代码的情况下给类增加新成员(属性和方法)

# 装饰器装饰类

# 使用函数装饰器,给类进行装饰,增加新的属性和方法
def kuozhan(cls):  # 参数是类
    def func():
        print('装饰器中新增类方法')

    cls.func = func
    cls.name = '装饰器中新增类属性'
    return cls  # 返回修改后的类


@kuozhan
class Demo():
    def love():
        print('学习python')


Demo.love()
print(Demo.name)
Demo.func()