Python之路【第十七篇】:装饰器

写代码的时候有一个原则,开放封闭原则(面向对象):对某些东西开放,对某些封闭,在装饰器这里,函数内部是封闭的,不允许改变函数的内部。

装饰器用来装饰函数,可以让函数在执行之前或者执行之后,做一些操作,让函数调用者的操作不变,就能在执行前后做一些操作。简单来说,装饰器感觉就类似于装修,提供一些额外的功能。

装饰器的本质就是将原函数封装到另一个函数里面。

装饰器原理剖析

关键点1

def f1():
    print('1')
def f1():
    print('2')
f1()

上面这段函数执行后,输出的结果为2,因为python解释器从上往下执行,先把第一个f1放进内存,碰到第二个f1函数后又把它放进内存,所以f1指的是第二个函数的内容。

关键点2

@符号:

    @符号具有特殊性,@函数名,碰到后,先执行函数,并且将其下面的函数名当作参数,如:

def outer(func):
    pass
@outer
def f1():
    pass
def f2():
    pass

碰到@outer之后,先执行outer函数,然后将f1作为参数,此时func=f1(原来的f1函数)

outer的返回值赋值给f1,此时f1=outer返回值,所以以后再执行f1,就执行新的f1函数

 关键点3

只要函数用了装饰器,函数就会重新定义为装饰器的内层函数,所以如果函数有参数的话,装饰器的内层函数也要有相应的参数来接收,即inner函数要有相应的参数,同时,func函数等于原来的函数,所以func函数也要有相应的参数

inner(*args,**kwargs)

ret  = func(*args,**kwargs)

以后写装饰器就按照上面的写法来,这样就不用担心参数的问题了,碉堡了。

装饰器例子:

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def outer(func):
    def inner(*args,**kwargs):
        print('')
        ret = func(*args,**kwargs)
        print('')
        return ret
    return inner

@outer
def f1(a1):
    print('aa')
    return a1

@outer
def f2(s1,s2):
    print('bb')
    return s1,s2

ret1 = f1(1)

ret2 = f2(2,3)

print(ret1,ret2)

上面的程序输出结果为:


aa


bb

1 (2, 3)

可以看到,在不改变函数的基础上,函数执行了一些别的操作。上面这是一个装饰器装饰一个或多个函数的场景

多个装饰器装饰一个函数

#!/usr/bin/env python
# -*- coding:utf-8 -*-

def outer0(func):
    def inner(*args,**kwargs):
        print('before')
        ret = func(*args,**kwargs)
        print('after')
        return ret
    return inner
def outer(func):
    def inner(*args,**kwargs):
        print('')
        ret = func(*args,**kwargs)
        print('')
        return ret
    return inner
@outer0
@outer
def f1():
    print('self')
    return None
f1()

输出结果为:

before

self

after

可以这样理解:

#part1
#一个新的函数,不妨叫这个函数为index
@outer
def f1(): print('self') return None

然后代码就变成了下面这样:

#part2
@outer0 def index(): pass

最后函数的执行顺序是这样的:先执行最外层的part2,即先输出before,在执行index函数,最后输出after,执行index函数的时候,就是执行part1,先输出'你',在输出'self',再输出'好'。

posted @ 2018-03-31 11:08  RongHe  阅读(146)  评论(0编辑  收藏  举报