人生苦短,我用python。

一、装饰器

装饰器:外部函数传入被装饰函数名,内部函数返回装饰函数名。

装饰器功能:引入日志、函数执行时间统计、执行函数前预备处理、执行函数后清理功能、权限校验等场景、缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 装饰器:外部函数传入被装饰函数名,内部函数返回装饰函数名。

def makeBold(fn): # 传入被装饰函数名
def wrapped():
return "<b>" + fn() + "</b>" # 调用被装饰函数
return wrapped # 返回装饰函数名

def makeItalic(fn):
def wrapped(): # 装饰函数,完成包裹数据
return "<i>" + fn() + "</i>"
return wrapped # 代表的是函数,并非执行函数

@makeBold # 装饰器,实际就是将test1作为makeBold的参数传入
def test1():
return 'hello world-1'

@makeItalic
def test2():
return 'hello world-2'

@makeBold # 后执行这个装饰器
@makeItalic # 先执行这个装饰器
def test3():
return 'hello world-3'

print(test1())
print(test2())
print(test3())

被装饰的函数无参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 无参数的函数
from time import ctime,sleep

def timefun(func):
def wrappedfunc():
print('%s called at %s' %(func.__name__,ctime()))
func()
return wrappedfunc

@timefun
def foo():
print('I am foo')

foo()

被装饰的函数有参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 被装饰的函数有参数
from time import ctime,sleep

def timefun(func):
def wrappedfunc(a,b):
print('%s called at %s'%(func.__name__,ctime()))
print(a,b)
func(a,b)
return wrappedfunc

@timefun
def foo(a,b):
print(a+b)

foo(3,5)

被装饰的函数有不定长参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 被装饰的函数有不定长参数
from time import ctime, sleep

def timefun(func):
def wrappedfunc(*args,**kwargs):
print('%s called at %s'%(func.__name__,ctime()))
func(*args,**kwargs)
return wrappedfunc

@timefun
def foo(a,b,c):
print(a+b+c)

foo(3,5,7)

装饰器中的return:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 装饰器中的return
from time import ctime, sleep

def timefun(func):
def wrappedfunc():
print("%s called at %s"%(func.__name__, ctime()))
return func()
return wrappedfunc

@timefun
def getInfo():
return '----haha----'

print(getInfo())

装饰器带参数,在原有装饰器的基础上,设置外部变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 装饰器带参数,在原有装饰器的基础上,设置外部变量
from time import ctime, sleep

def timefun_arg(pre='hello'):
def timefun(func):
def wrappedfunc():
print('%s called at %s %s'%(func.__name__,ctime(),pre))
return func()
return wrappedfunc
return timefun

@timefun_arg('python')
def foo():
print('I am foo')

foo() #可以理解为foo()==timefun_arg("python")(foo)()

类装饰器(扩展,非重点):

装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象。在Python中一般callable对象都是函数,但也有例外。只要某个对象重写了 __call__() 方法,那么这个对象就是callable的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Test():  # 用Test来装作装饰器对test函数进行装饰的时候,首先会创建Test的实例对象
def __init__(self,func): # 会把test这个函数名当做参数传递到__init__方法中
print('---初始化---')
print('func name is %s'%func.__name__)
self.__func = func # 为了能够在__call__方法中调用原来test指向的函数体,需要一个实例属性来保存这个函数体的引用
def __call__(self): # __call__()方法可以将类实例变成一个可调用对象
print('---装饰器中的功能---')
self.__func()

@Test
def test(): # test函数相当于指向了用Test创建出来的实例对象
print('---test---')

test() # 在使用test()进行调用时,就相当于让这个对象(),因此会调用这个对象的__call__方法

持续更新…

最后更新: 2018年12月04日 16:03

原始链接: http://pythonfood.github.io/2017/12/30/python装饰器/

× 多少都行~
打赏二维码