Python3-装饰器

装饰器(语法糖)

装饰器的本质:一个闭包函数

装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展

例子1.

给hahaha函数加上一个timmer(计算函数执行时间)的功能。

import time
def timmer(func):
    #函数名可以当做函数的参数
    def inner():
        start = time.time()
        func()
        end = time.time()
        print(start - end)
    return inner

# 语法糖
@timmer       # @把hahaha函数名作为参数传到timmer(),执行了一次, 然后进行了重新赋值 hahaha = timmer(hahaha) --> inner()
def hahaha():
    time.sleep(0.1)
    print('aaaa')

# time(hahaha)      不能改变这个函数的调用方式
# 也不能修改源代码
# hahaha = timmer(hahaha)       timmer(hahaha)函数的执行结果返回 inner函数的内存地址,然后赋值给hahaha
# hahaha()  就等同于  inner()

hahaha()

装饰器的设计模式:开放封闭原则

开放:对扩展是开放的

封闭:对修改是封闭的

 

刚刚我们讨论的装饰器都是装饰不带参数的函数,现在要装饰一个带参数的函数怎么办?

import time

def timer(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        end_time = time.time()
        print(end_time - start_time)
    return inner

@timer
def func1(a):
    time.sleep(2)
    print(a)

func1('bb')

 

带参数的装饰器

def outer(flag):
    def timer(func):
        def inner(*args, **kwargs):
            if flag:
                print('执行函数之前要做的')
            func(*args, **kwargs)
            if flag:
                print('执行函数之后要做的')
        return inner
    return timer

@outer(True)
def func2(mode):
    print(111, mode)

func2('rrr')

 

多个装饰器装饰同一个函数

有些时候,我们也会用到多个装饰器装饰同一个函数的情况。

单个装饰器:


def first(func):
print('%s() was post to first()' % func.__name__)
def _first(*args, **kwargs):
print('Call the function %s() in _first().' % func.__name__)
return func(*args, **kwargs)
return _first

@first # first(test) test = first(test) --> _first
def test():
return 'hello world!'

test()

输出:

test() was post to first()
Call the function test() in _first().

 多重装饰器:

def first(func):
    print('%s() in first' % func.__name__)
    def _first(*args, **kwargs):
        print('Call the function %s() in _first().' % func.__name__)
        return func(*args, **kwargs)
    return _first

def second(func):
    print('%s() in second()' % func.__name__)
    def _second(*args, **kwargs):
        print('Call the function %s() in _second().' % func.__name__)
        return func(*args, **kwargs)
    return _second


@first      # first(test)  test = first(test) --> _first
@second     # second(test) test = second(test) --> _second
def test():
    return 'hello world!'

test()

输出:

test() was post to second()
_second() was post to first()
Call the function _second() in _first().
Call the function test() in _second().

实际上它是相当于下面的代码:

>>> def test():
    return 'hello world'

>>> test=second(test)
test() was post to second()
>>> test
<function _second at 0x000000000316D3C8>
>>> test=first(test)
_second() was post to first()
>>> test
<function _first at 0x000000000316D358>
>>> test()
Call the function _second() in _first().
Call the function test() in _second().
'hello world'
>>>

 

posted @ 2018-12-26 12:05  下山打老虎i  阅读(215)  评论(0编辑  收藏  举报