python的高级技巧中,一定有装饰器的一席之地。目前掌握的知识还不是很多,我尽量用自己能理解的语言描述清楚。
什么是装饰器?
先贴上官方解释 decorator官方解释 ,看不懂英文的可以将网页翻译成中文再看,凡是都需要耐心。。。
个人愚见:
在遵循 开发封闭 原则的基础上,对原有模块功能进行扩展所用的代码块,就可以解释为装饰器。当然,这只是从功能上解释了下,定义还是看 decorator官方解释 吧。
代码样例
假如要写一个关于url请求方法的模块,为后期减少使用者的配置,定义如下:
{201: put,202: get,203: head,204: delete},调用时传入相应字符即可调用对应请求方法。目前我能想到的有下面4中方法(好像高中解数学题目_)。
以下所有方法忽略异常情况,仅讨论实现方式的区别。
方法一:使用字典完成映射 UrlDict.py
def put():
print('put')
def get():
print('get')
def delete():
print('delete')
def head():
print('head')
def get_method(method):
run_method = METHOD_DICT[method]
return run_method
def run(run_num):
run_method = get_method(run_num)
run_method()
METHOD_DICT = {
'201': put,
'202': get,
'203': head,
'204': delete,
}
if __name__ == '__main__':
run('202')
run('201')
run('203')
run('204')
优点:简洁明了,实现全部需求。
缺点:每增加一个请求方法,就要在method_dict中添加一对值。如果方法过多,method会过于庞大,且不利于 开发封闭 原则。
方法二:使用globals局变量完成 UrlGlobals.py
def put():
print('put')
def get():
print('get')
def delete():
print('delete')
def head():
print('head')
def get_method(method):
run_method = globals()[method]
return run_method
def run(run_num):
run_method = get_method(run_num)
run_method()
if __name__ == '__main__':
run('put')
run('head')
run('get')
run('delete')
优点:简洁明了,遵循 开发封闭 原则。
缺点:未实现以数字(字符)代替请求的需求,调用配置需使用准确的方法。实质是第一种方法中的METHOD_DICT由globals()替换。
方法三:使用getattr完成 UrlGetattr.py
class RequestUrl(object):
@staticmethod
def put():
print('put')
@staticmethod
def get():
print('get')
@staticmethod
def delete():
print('delete')
@staticmethod
def head():
print('head')
def get_method(self, method):
run_method = getattr(self, method)
return run_method
def run(self, method):
run_method = self.get_method(method)
run_method()
if __name__ == '__main__':
req = RequestUrl()
req.run('put')
req.run('head')
req.run('get')
req.run('delete')
优点:简洁明了,遵循 开发封闭 原则。
缺点:未实现以数字(字符)代替请求的需求,调用配置需使用准确的方法。
方法四:使用装饰器完成 UrlDecorator.py
METHOD_DICT = {}
def set_route(run_num):
def set_func(func):
METHOD_DICT[run_num] = func
def call_func(*args, **kwargs):
return func(*args, **kwargs)
return call_func
return set_func
@set_route('201')
def put():
print('put')
@set_route('202')
def get():
print('get')
@set_route('204')
def delete():
print('delete')
@set_route('203')
def head():
print('head')
def get_method(method):
run_method = METHOD_DICT[method]
return run_method
def run(run_num):
run_method = get_method(run_num)
run_method()
if __name__ == '__main__':
run('202')
run('201')
run('203')
run('204')
优点:完成所有需求,遵循 开放封闭 原则。
缺点:使用装饰器理解难度高。
总结
在实际开发过程中,开放封闭 原则是很重要的,因为代码一旦上库运行,后续修改是很困难的,很难清楚的知道有多少处调用。后面3种虽然都遵循了这一原则,只有使用装饰器的方式满足了全部需求。
所以从满足需求来看,只有第一种和最后一种满足了需求,而第一种随着功能的增加,要逐渐修改字典变量METHOD_DICT的长度,虽然修改这个本身并不复杂,但有高大上的解决方式,又有什么理由不去学习呢?
网友评论