048 装饰器

装饰器

  • 器:只的就是工具
  • 函数:也能够说是一个工具,须要用到这个工具的时候能够直接拿过来用
  • 装饰器:是指对一个工具备装饰的做用,也就是说能够为一个工具添加其余的功能做用
  • 因此定义装饰器其实就是至关于在定义一个函数,只不过这个函数的功能是用来为其余函数添加额外的功能
  • 装饰器至关于一个函数A,它用来装饰另外一个函数B,为函数B添加其余的功能,这就是用一个函数A去装饰另外一个函数B

1、无参装饰器

1.为何要使用装饰器

  • 就比如咱们已经完成了一个项目,可是咱们须要修改其中某个方法,可是咱们又不想修改他原来的

调用方法,那这个时候咱们就可使用装饰器来实现修改python

  • 使用装饰器的时候咱们须要遵循两点原则
    • 不修改被装饰对象的源代码
    • 不修改被装饰对象的调用方式

2.改变源代码方式修改函数的功能

# 原函数
def name():
    print('hello xichen')
name


# 为原函数增长功能
# 修改源代码的方式
def name():
    print('---------')
    print('hello xichen')
    print('---------')
name()

3.修改调用方式

import time

def index():
    print('welcome to index')
    time.sleep(1)


def func(func):
    start = time.time()
    fun()
    end = time.time()
    print(start-end)

func(index)

4.用装饰器来修改

# 没有返回值的
import time

def index():
    print('welcome to index')
    time.sleep(1)

def func(fun):
    def f():# 从新建立的index
        start = time.time()
        fun() # 真正的index
        end = time.time()
        print(start-end)
    return f
index = func(index) # index = func(),其实就是等于f()
index()
# 有返回值的
import time

def index():
    print('welcome to index')
    time.sleep(1)
    
    return 123

def func(fun):
    def f():# 从新建立的index
        start = time.time()
        res = fun() # 真正的index
        end = time.time()
        print(start-end)
        return res
        
    return f
index = func(index) # index = fun,其实就是等于f()
res = index()
print(res)

5.完善的装饰器

  • 若是原始的index()有返回值的时候,那么咱们用装饰器为其添加的功能的最后返回值也应该和原函数的返回值相同
  • 因此这个时候咱们就能够哪个变量来接收装饰器最后的值而且返回
  • 也就是说咱们须要同步原始的函数返回值和咱们后来新建的一个添加功能的函数的返回值
import time

def func(fun):
    def f():
        start = time.time()
        res = fun()
        end = time.time()
        print(end - start)
        return res
    return f

def index():
    print('hello xichen')
    time.sleep(1)

    return 123

index = func(index)
res = index()
print(res)
  • 若是原始的index()方法须要传参,那么咱们以前的装饰器是没法实现该功能的,因为有后来新建的添加功能的函数就是=index(),因此给后来新建的函数方法传参便可。
import time
def func(fun):
    def f1(*args, **kwargs):
        print('args:', args)
        print('kwargs:', kwargs)
        start = time.time()
        res = fun(*args, **kwargs)
        end = time.time()
        print(end - start)
        return res
    return f1

@func
def index(a,b=1):
    print('a:', a)
    print('b', b)
    print('hello xichen')
    time.sleep(1)

    return 123

res = index(1)
print(res)

6.装饰器语法糖

  • 在被装饰函数正上方,而且是单独一行写上@装饰器名
  • 用语法糖的话会更精简代码,并且往后咱们用的装饰器都是已经定义好的,能够直接拿过来用
import time

def func(fun):
    def f(*args, **kwargs):
        print('args:', args)
        print('kwargs:', kwargs)
        start = time.time()
        res = fun(*args, **kwargs)
        end = time.time()
        print(end - start)
        return res
    return f
@func
def index(a,b=1):
    print('a:', a)
    print('b', b)
    print('hello xichen')
    time.sleep(1)

    return 123

res = index(1)
print(res)

7.装饰器模板

  • 咱们只要记住了装饰器的模板,其实就等于已经会了如何去用装饰器了
def func(fun):
    def f(*args,**kwargs):
        res = fun(*args,**kwargs)
        # 给原来的函数加功能
        return res
    return f

2、有参的装饰器

1.有参的三层装饰器

def data(enter):
    def func(fun):
        def f(*args,**kwargs):
            if enter == 'file':
                uname = input('uname:')
                upwd = input('upwd:')
                if uname == 'xichen' and upwd == '123':
                    print('登录成功')
                    res = fun(*args,**kwargs)
                    return res
                else:
                    print('登陆失败')
            else:
                print('数据来源数据库,不可用')
        return f
    return func
@data('file')
def shopping():
    print('欢迎shopping')
    return 123

res = shopping()
print(res)

2.双层装饰器

def demo2(func2):
    def add_func2(*args,**kwargs):
        print('-------------')
        func2(*args,**kwargs) # func2此时是demo1装饰的函数add,添加的功能的add_func1
        print('-------------')

        return func2
    return add_func2


def demo1(func1):
    def add_func(*args,**kwargs):
        print('***********')
        func1(*args,**kwargs) # func1是被demo装饰的函数add
        print('***********')

        return func1
    return add_func

def add():
    print('hello')

# 先运行的是先装饰的函数demo1
add = demo1(add) # add = func1,也就是在调用add_func1,add返回的是add_func1
add = demo2(add) # add = func2,也就是在调用add_func2,add返回的是add_func2
add()

3.双层装饰器模板

def demo2(fun2):
    def add_func2(*args,**kwargs):
        res = fun2(*args,**kwargs)
        # 添加功能
        
        return res
    return add_fun2


def demo1(fun1):
    def add_func1(*args,**kwargs):
        res = fun1(*args,**kwargs)
        # 添加功能
        
        return res
    return add_fun1


def add():
    print('hello xichen')
    
    return 123


add = demo1(add)
add = demo2(add)
add()

4.三层装饰器模板

def demo(enter):
    def func(fun):
        def f(*args,**kwargs)
            # 添加功能
            res = fun(*args,**kwargs)
        return f
    return func

@demo(参数---enter)
def add()
    print('hello xichen')
    
    return 123

res = add()
res()
  • 因为两层的装饰器,参数必须得固定位func,可是三层的装饰器解除了这个限制。咱们不单单可使用单个参数的三层装饰器,多个参数的只须要在三层装饰器中多加入几个参数便可。也就是说装饰器三层便可,多加一层反倒无用。
相关文章
相关标签/搜索