什么是装饰器

装饰器是指装饰的工具(函数),这个函数具有装饰作用.因此定义装饰器就是定义一个函数,只不过该函数的功能是用来为其他函数添加额外的功能.

注意: 装饰器本身其实是可以任意可调用的对象

​ 被装饰的对象也可以是任意可调用的对象

装饰器本质就是一个函数A,装饰的对象也是一个函数B,用一个函数A去装饰一个函数B

装饰器的实现必须遵循两大原则:

  1. 不改变函数B的调用方式
  2. 不改变函数B的源代码

装饰器的使用

改变源代码

import time


def index():
    start = time.time()
    print('welcome to index')
    time.sleep(1)
    end = time.time()
    print(start-end)


index()

welcome to index
-1.0000019073486328

编写重复代码

import time


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


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


start = time.time()
index()
end = time.time()
print(start-end)

start = time.time()
f2()
end = time.time()
print(start-end)

welcome to index
-1.0004847049713135
welcome to index
-1.0000324249267578

第一种传参方式:改变调用方法

import time

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

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


time_count(index)

welcome to index
-1.0003643035888672

第二种传参方式:包给函数-外包

import time

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

def time_count(func):
    # func = 最原始的index
    def wrapper():
        start = time.time()
        func()
        end = time.time()
        print(start-end)
    return wrapper

# f = time_count(index)
# f()


index = time_count(index)  # index为被装饰函数的内存地址,即index = wrapper
index()  # wrapper()

welcome to index
-1.0000269412994385

装饰器语法糖

在被装饰函数正上方,并且是单独一行写上@装饰器名

import time
def deco(func):
    def f1(*args, **kwargs):
        print('args:',args)  # (10,)
        print('kwargs:',kwargs)
        start = time.time()
        # *args = *(10,) 10
        res = func(*args, **kwargs)  # 真正的index()
        end = time.time()
        print(end - start)
        return res
    return f1

@deco   # 语法糖(更精简的代码)   index = deco(index)
def index(x, a=1):
    print('x', x)
    print('a', a)
    print('hello index')
    time.sleep(1)

    return 123

#重新创建的index = deco(index真正的index)
index = deco(index)  # index  = f1
index(10)  # f1(1)

args: (10,)
kwargs: {}
args: (10,)
kwargs: {}
x 10
a 1
hello index
1.00038743019104
1.00038743019104

三层装饰器

给双层装饰器加参数

# 判断账号密码来自于哪个地方
def auth(engine):
    def login(func):
        def inner(*args, **kwargs):
            # 登录功能
            if engine == 'file':
                username = input('usrename:')
                pwd = input('pwd:')
                if username == 'nick' and pwd == '123':
                    print('登录成功')
                    res = func(*args, **kwargs)  # shopping()
                    return res
                else:
                    print('登录失败')

            elif engine == 'db':
                print('账号密码来自于数据库,非法请求')

        return inner
    return login

@auth('db')
def shopping():
    print('shopping')


# login = auth('db')  # login = login
# shopping = login(shopping)  # shopping = inner
shopping() # inner()

装饰器模板

双层装饰器

def outter(func):
    def inner(*args,**kwargs): #wrapp是未来要运行的函数
        #加功能
        res=func(*args,**kwargs) #func是被装饰的函数
        return res
    return inner

@outter
def shopping():
    print(shopping)
        

三层装饰器

def sancneg(engine):
    def outter(func):
        def inner(*args, **kwargs): #wrapper是未来要运行的函数
            # 加功能
            print(engine)
            res = func(*args, **kwargs) #func是被装饰的函数
            return res

        return inner
    
    return outter

@sancneg('file')
def shopping():
    print(shopping)
        
posted on 2019-08-12 15:39  黑糖A  阅读(104)  评论(0编辑  收藏  举报