装饰器

装饰器

定义

在不改变函数的源码和调用方式的情况下,给函数加功能

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

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

分类

双层装饰器

例如,函数world是一个完整的功能函数,想要给world函数增加一个程序运行时长的功能,但不改变world函数的源码和调用方式,如何实现呢?

这样,我们就可以用到装饰器了:

import time

def time_world(func): # func是真正的world
    """装饰函数"""
    def add():
        # 增加功能部分
        t1 = time.time()  # func() == world()
        func()
        t2 = time.time()
        print(t2 - t1)
    return add

def world():
    """被装饰函数"""
    print('hello world!')
    time.sleep(1)
world = time_world(time)
world() # 调用方式不变world(),实际是调用add()

"""
用语法糖来调用更简单
@time_world
def world():
    """被装饰函数"""
    print('hello world!')
    time.sleep(1)
world()
"""

三层装饰器

三层装饰器就是给双层装饰器加参数

例如,给shopping函数增加登录功能,并且传入登录方式变量,如果登录方式是file,则登录成功,如果是db,则登录非法。

因为涉及到传值,双层装饰器显然实现较为困难,因此,引入三层装饰器:

def three(gen):
    def login(func):
        def inner(*args,**kwargs): # 接收shopping传的所有值
            if gen == 'file':
                name = input('name:')
                pwd = input('password:')
                # 假定name,pwd固定
                if name == 'wzh' and pwd == '123':
                    print('success!')
                    res = func(*args,**kwargs)
                    return res
                else:
                    print('default')
             elif gen == 'db':
                print('登录非法!')
		return inner
    return login

@three('file')
def shopping():
    print('shopping!')
    
shopping()         

双层语法糖

执行顺序相关

# 双层语法糖
def outer1(func):
    def inner(*args,**kwargs):  # 接收index里的参数
        """功能模块"""
        print('----------------')
        res = func(*args,**kwargs)
        print('----------------')
        return res   # 返回index里的参数
    return inner
def outer2(func):
    def inner(*args,**kwargs):  # 接收index里的参数
        """功能模块"""
        print('****************')
        res = func(*args,**kwargs)
        print('****************')
        return res   # 返回index里的参数
    return inner

@outer1
@outer2
def f():
    print('success')
f()

"""
----------------
****************
ssss
****************
----------------
"""

装饰器模板(重要)

# 双层装饰器
def two(func):
    def two_inner(*args,**kwargs):
        """功能模块"""
        res = func(*args,**kwargs)
		return res
    return inner
@two
def f():
    pass
f()

# 三层装饰器
def three(value):
    def two(func):
        def innere(*args,**kwargs):
            """功能模块"""
            print(value)
            res = func(*args,**kwargs)
            return res
        return inner
    return two
@three('shabi')
def f():
    pass
f()
posted @ 2019-08-12 16:24  SweetJack  阅读(91)  评论(0编辑  收藏  举报