今天的一个小任务,想要实现这么一个功能。在一个类中调用一个函数后,为了保证能及时释放资源,需要在程序执行后单独进行清理操作。
要求是尽可能不改变原来的函数调用方式。同样的东西,java实现比较容易,但是这里要求用python2,请教了前辈。发现其实就是一个装饰器的使用。
以下这个是网上找的示例,很清晰。比较适合我这种初级人员。
怎么写一个装饰器
python2,为一个函数添加额外功能的写法是这样的。
def debug(func):
def wrapper():
print "[DEBUG]: enter {}()".format(func.__name__)
return func()
return wrapper
def say_hello():
print "hello!"
say_hello = debug(say_hello) # 添加功能并保持原函数名不变
上面的debug函数其实已经是一个装饰器了,它对原函数做了包装并返回了另外一个函数,额外添加了一些功能。因为这样写实在不太优雅,在后面版本的Python中支持了@语法糖,下面代码等同于早期的写法。
def debug(func):
def wrapper():
print "[DEBUG]: enter {}()".format(func.__name__)
return func()
return wrapper
@debug
def say_hello():
print "hello!"
say_hello()
这是最简单的装饰器,但是有一个问题,如果被装饰的函数需要传入参数,那么这个装饰器就坏了。因为返回的函数并不能接受参数,你可以指定装饰器函数wrapper接受和原函数一样的参数,比如:
def debug(func):
def wrapper(something): # 参数必须和原来的保持一致
print "[DEBUG]: enter {}()".format(func.__name__)
return func(something)
return wrapper # 返回包装过函数
@debug
def say(something):
print "hello {}!".format(something)
say(123)
这样就解决了一个问题,但又多了个问题。因为函数的参数是可变的,有很多种变化?还好Python提供了可变参数*args和关键字参数**kwargs,有了这两个参数,装饰器就可以用于任意目标函数了。
def debug(func):
def wrapper(*args, **kwargs):
print "[DEBUG]: enter {}()".format(func.__name__)
print 'Prepare and say...',
return func(*args, **kwargs)
return wrapper # 返回
@debug
def say(something):
print "hello {}!".format(something)
say(1231,123,123,123)
以上就是初级的装饰器写法。
参考地址:
详解Python的装饰器
高级的需要
函数的闭包和装饰器的接口约定有一定了解。后面在学习吧
当然目前只是一个想法,还需要和客户方对接,看可行不可行。继续跟进这个问题。