Python的装饰器decorator


作者:王大为
时间:2016-10-19


一、装饰器的本质

本质:装饰器本身就是一个函数,高阶函数+嵌套函数==>装饰器
原则

* 1、不能修改被装饰函数的源代码
    * 2、不能修改被装饰函数的调用方式

二、装饰器需要的知识储备

1、函数即变量
2、高阶函数
3、嵌套函数

三、函数即变量

形象的比喻,整个内存是一座大楼,其中每个房间存储的是对应的值,而变量名就是对应房间的门牌;一个房间的门牌可以有好几个,也就是不同的变量名可以对应同一段内存地址

python的DBC模组 python decorator模块_嵌套


对比一下四种方式的函数调用说明:变量先声明后调用

第一种

python的DBC模组 python decorator模块_python_02


python的DBC模组 python decorator模块_python的DBC模组_03


第二种

python的DBC模组 python decorator模块_python_04


python的DBC模组 python decorator模块_高阶函数_05


第三种

python的DBC模组 python decorator模块_高阶函数_06


python的DBC模组 python decorator模块_变量名_07


第四种

python的DBC模组 python decorator模块_python的DBC模组_08


python的DBC模组 python decorator模块_python的DBC模组_09


四、高阶函数

定义:满足下面条件二选一即可

* a,把一个函数名当做实参传给另外一个函数(在不修改被装饰函数源代码的情况下为其添加功能)
* b,返回值中包含函数名(不修改函数的调用方式)

举例如下:

python的DBC模组 python decorator模块_高阶函数_10

python的DBC模组 python decorator模块_变量名_11


五、嵌套函数

定义:函数中嵌套函数(在一个函数体内使用def定义一个局部函数)

举例如下:

python的DBC模组 python decorator模块_python_12

python的DBC模组 python decorator模块_高阶函数_13


六、装饰器

1、基本装饰器
code代码:

import time


def timer(func):
    def inner():
        start_time = time.time()
        func()
        stop_time = time.time()
        print('the func run time is %s' % (stop_time - start_time))
    return inner


@timer
def f1():
    time.sleep(1)
    print('in the f1')

f1()

原理:

python的DBC模组 python decorator模块_python的DBC模组_14


2、装饰的函数带有参数,需要万能参数(*args, **kwargs)

import time


def timer(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        stop_time = time.time()
        print('the func run time is %s' % (stop_time - start_time))
    return inner


@timer
def f1(name):
    time.sleep(1)
    print('in the f1,%s' % name)

f1('linda')

3、装饰的函数带有返回值,需要指定返回值

import time


def timer(func):
    def inner():
        start_time = time.time()
        ret = func()
        stop_time = time.time()
        print('the func run time is %s' % (stop_time - start_time))
        return ret
    return inner


@timer
def f1():
    time.sleep(1)
    print('in the f1')
    return 'hello'
print(f1())

4、单层装饰器最终版

import time


def timer(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        ret = func(*args, **kwargs)
        stop_time = time.time()
        print('the func run time is %s' % (stop_time - start_time))
        return ret
    return inner


@timer
def f1(name):
    time.sleep(1)
    print('in the f1,%s' % name)
    return 'hello'
print(f1('linda'))

5、多层装饰器
代码code:

def timer1(func):
    def inner1(*args, **kwargs):
        print('begin in the timer1')
        ret = func(*args, **kwargs)
        print('stop in the timer1')
        return ret
    return inner1


def timer2(func):
    def inner2(*args, **kwargs):
        print('begin in the timer2')
        ret = func(*args, **kwargs)
        print('stop in the timer2')
        return ret
    return inner2


@timer1
@timer2
def f1(name):
    print('in the f1,%s' % name)
    return 'hello'
f1('linda')

结果result:

python的DBC模组 python decorator模块_python_15

原理如下:

*1、编译时:从下往上一层一层嵌套、编译
*2、执行时:从上往下一层一层调用、执行

python的DBC模组 python decorator模块_嵌套_16


6、可以加参数的装饰器(web使用)
代码code:

def timer1(position):
    print('position:', position)

    def inner1(func):
        def inner2(*args, **kwargs):
            if position == 'local':
                print('begin in the timer1')
                ret = func(*args, **kwargs)
                print('stop in the timer1')
                return ret
            else:
                print('你不是本地local用户.')
        return inner2
    return inner1


@timer1(position='now')
def f1(name):
    print('in the f1,%s' % name)
    return 'hello'
f1('linda')

6.1、当装饰器的参数为@timer1(position=’local’)

结果result:

python的DBC模组 python decorator模块_变量名_17


6.2、当装饰器的参数为@timer1(position=’remote’)

结果result:

python的DBC模组 python decorator模块_python的DBC模组_18