python中的装饰器

  • baagee 发布于 2017-07-27 14:13:49
  • 分类:Python
  • 1204 人围观
  • 20 人喜欢

0. 装饰器的作用有:

  1. 引入日志
  2. 函数执行时间统计
  3. 执行函数前预备处理
  4. 执行函数后清理功能
  5. 权限校验等场景
  6. 缓存

装饰器能在不改变被装饰对象的同时增加了对象的功能。传递一个函数,返回一个处理后的函数。和下面这种通过闭包实现的一样:

1,装饰器的原理

def check(func):
    def inner():
        print('check...')
        func()
    return inner

def test():
    print('over')

test = check(test)
test()

单独的调用test()只会打印出over,但是通过闭包就是这个结果了:

check...
over
[Finished in 0.1s]

其实装饰器就是这个原理:

def check(func):
    def inner():
        print('check...')
        func()
    return inner

@check
def test():
    print('test1')

@check
def test2():
    print('test2')

test()
test2()

函数前面使用@装饰器名来给函数扩展功能(在不修改函数代码的前提下)。@check其实就相当于test=check(test)

2,两个装饰器同时装饰

def check1(func):
    def inner():
        print('check1...')
        return '<i>' + func() + '</i>'
    return inner


def check2(func):
    def inner():
        print('check2...')
        return '<sapn>' + func() + '</span>'
    return inner


@check2
@check1
def test():
    return 'test'

print(test())

给test()函数同时增加两个装饰器(check1和check2)

name它们的装饰顺序是怎么样的呢?

check2...
check1...
<sapn><i>test</i></span>
[Finished in 0.1s]

调用装饰器的顺序和我们写的一样,从上到下依次,但是对装饰的函数的装饰正好和调用相反(从下到上,只有下面的装饰器执行完毕后才能执行上面的装饰器)。

3. 装饰有形参的函数

例1:

def check1(func):
    def inner(a, b):
        print('check1...')
        return '<i>' + str(func(a, b)) + '</i>'
    return inner


@check1
def test(a, b):
    return a + b

print(test(3, 4))

在给装饰的闭包函数定义和原函数一样数量的形参,在闭包函数里调用原函数时传递进去。

结果就是:

check1...
<i>7</i>
[Finished in 0.0s]

例2:

def check1(func):
    def inner(*args, **kwargs):
        print('check1...')
        return '<i>' + str(func(*args, **kwargs)) + '</i>'
    return inner


@check1
def test(a, b, c, *args, **kwargs):
    print('c=%d' % c)
    print(args)
    print(kwargs)
    return a + b


@check1
def test1(a, b, c, d):
    print('a=%d b=%d c=%d d=%d' % (a, b, c, d))

print(test(1, 2, 4, 4, 5, 6, 7, name='fsdfgs', age=55))
test1(0, 3, 4, 5)

例1是对固定参数数量的函数进行装饰,这个是对不定长参数的函数进行装饰,结果是:

check1...
c=4
(4, 5, 6, 7)
{'age': 55, 'name': 'fsdfgs'}
<i>3</i>
check1...
a=0 b=3 c=4 d=5
[Finished in 0.1s]

4. 带参数的装饰器

可以在装饰器上传递参数例如:

def check(p):
    def check_1(func):
        print('===========>'+p)
        def inner():
            if p == '777':
                print('77777777777777777777')
            else:
                print('LLLLLLLLLLLLLLLLLLLL')
            print('check1...' + p)
            func()
        return inner
    return check_1


@check('666')
def test():
    print('test')


@check('777')
def test2():
    print('test2')

test()
test2()

check这个装饰器在装饰时传递一个参数,这时就要写2层闭包了,依次把函数return,check_1才是真正起装饰的函数,传递的参数可以在里面两层函数里使用,对于不同的参数,我们采用的不同的装饰最后的结果是:

===========>666
===========>777
LLLLLLLLLLLLLLLLLLLL
check1...666
test
77777777777777777777
check1...777
test2
[Finished in 0.1s]

为什么666,777在前面打印呢?这时因为在代码执行时,即使函数不调用,但是此时函数已经被装饰了,调用check_1,打印p,然后把装饰后的函数返回给原函数。为了验证就是我说的这样,其实很简单,不调用就行了,看看执行效果:


转载请说明出处:baagee博客 » python中的装饰器
标签: Python 装饰器

评论

点击图片切换
还没有评论,快来抢沙发吧!