Li RUONAN


一枚行走在前端道路上的程序媛 ~~


聊聊Decorator

##Decorator
最近在看Python,发现ES6+之后的语法,与Python越来越像了,实在是有趣的紧,莫名的喜欢这门语言。看了高级特性和函数式编程,对装饰器运用的不够熟练,于是想要写写关于decorator的总结。

decorator就是一个返回函数的高阶函数,可以增强部分函数的功能,但不又修改原函数的定义。例如:在运行某个函数的过程中,我们总想着给这个函数增加一些附加性的功能,如日志信息,监控信息等。这种在代码运行期间能动态增加功能的方式,就是我们常说的“装饰器”。

以下是Python2.7的语法,是廖雪峰前辈的习题,在这里可以解释下~~

编写一个decorator,能在函数调用的前后打印出’begin call’和’end call’的日志。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import functools

def log(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print 'call begin %s' % func.__name__
func_tmp = func(*args, **kw)
print 'call end %s' % func.__name__
return func_tmp
return wrapper

@log
def hello():
print 'hello world'

思考一下能否写出一个@log的decorator,使它既支持:@log,也支持 @log(‘execute’)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import functools
def log2(*text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print '%s!' % text
return func(*args, **kw)
return wrapper
return decorator

@log2('')
def f1():
pass
@log2('hello')
def f2():
pass

def main():
f1()
f2()
if __name__ == '__main__':
main()

这里其实不是很符合要求啦,希望不传入or传入字符串,但是上述代码至少要传入空字符串,因此想到不能用可变参数来解决这个问题,尝试用判断对象类型的方法,传入新的参数。

代码如下:
isinstance(object,type)
作用:判断一个对象是否是已知类型

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
#--coding utf8--
@log('execute')
def log(args=0):
def wrapper(func):
print 'call %s' % func.__name__

if isinstance(args, str):
print args
return wrapper
else:
return wrapper

@log
def now():
pass

@log(' ')
def then():
pass

@log('execte')
def next():
pass

now()
next()