美文网首页Python
python装饰器decorator学习——完成映射

python装饰器decorator学习——完成映射

作者: 做劲霸男人_31bb | 来源:发表于2019-04-22 19:21 被阅读68次
    decorator.jpg

    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的长度,虽然修改这个本身并不复杂,但有高大上的解决方式,又有什么理由不去学习呢?

    相关文章

      网友评论

        本文标题:python装饰器decorator学习——完成映射

        本文链接:https://www.haomeiwen.com/subject/espugqtx.html