zoukankan      html  css  js  c++  java
  • python3 装饰器应用举例

    引子

      python 中的装饰器是oop(面向对象编程)设计模式、之装饰器模式的一个应用、由于有语法糖衣的缘故、所以写起来也更加方便

    从一个比较经典的应用场景来讲解装饰器

      有过一定编程经历的工程师、应该都遇到过这样的场景。有一些老的API过时了但是在一段时间内它还是可用的,只是平台会把

      它标记为不推荐、也就是说这个API在新的版本里应该不会存在了。比如python-2.x 的时候有raw_input这个函数、但是到了  

      python-3.x的时候就没有了,在过渡时期平台通常会把将要过时的API标记成“过时”。它是怎么做到的呢?我觉得可行的方法

      有两个 1): 用工程师的“寿命”为代价通过手工劳动解决问题   2): 用装饰器优雅的解决

    用寿命来解决问题

      1.1 假设你编写了一个非常牛逼的库、里面包含了一个非常牛逼的函数、它可以完成两个数相加。一开始你的代码是这样的

    def add_fun(x,y):
        """
        实现两个数相加、并返回合
        """
        return x+y

      1.2 一段非常长的时间后、你的库在社区中大火、大家也都称你为大神;可是你突然发现了一个问题 add_fun 这个函数以“_fun”

      结尾真的够pythonic吗? 后来你还是决定把它改成add这样的函数名,可是有太多的程序依赖于你这个库的add_fun函数了,

      如果你突然把这个add_fun函数给改了,那些依赖于这个函数的程序由于再也找不到这个函数了,那么它们会报错,这个明显

      不是你想看到的;最后你还是决定单独增加一个add方法同时保留add_fun

    def add_fun(x,y):
        """
        实现两个数相加、并返回合
        """
        return x+y
    
    def add(x,y):
        """
        实现两个数相加、并返回合
        """
        return x+y   

      1.3 你开始为你这一个改动付出代价(网络上一时有无数人都在问你同一个问题),无数的人在问你为什么会有两上功能完全一样的函数?

      于是你把这个问题加到了FQA列表、并且还在你的代码中明确的指出了“add_fun已经过时”

    def add_fun(x,y):
        """
        实现两个数相加、并返回合
        """
        
        print("add_fun 函数已经过时")
        return x+y
    
    def add(x,y):
        """
        实现两个数相加、并返回合
        """
        return x+y 

      1.4 问题是解决了,几天过你可能会发现自己掉粉了,多数人对你这种简单粗暴的方法表示了失望。 有来说一下你的改法有什么问题吧、

      1): 你给出函数没办法“封闭”,“封闭”是oop编程中的一个术语,指的你定义好的类、函数应该是功能上完备的,不应该再改了,想

      一下如果“场效应管”、“二极管”、“pn结” 这种基础元器件动不动就要改一下,这种感觉就像你是在对一个身在100楼的程序猿说,

      你好好上你的班、不过我要修一下大楼的地基。回到程序上来你用什么来保存你的改动不会引入新的bug ?

      2): 一个函数还好、如果你成千上万个?那么你这成千上万个都没有封闭、而且每一个你都要改一下、你工作量也不是一般的小、人在

      重复劳动下容易出错。

     【巧用装饰器解决问题

      先定义一个函数它可以用来包装那些过时的函数、代码如下

    def deprecated(fun):
        """deprecated函数会返回一个叫inner的函数、inner函数会返回
        fun调用的结果,与直接调用fun得到值不同的是inner会先打印一行提示
        表明fun已经过时
        """
        def inner(x,y):
            print("{fun.__name__} 函数已经过时".format(fun=fun))
            return fun(x,y)
        return inner
    
    
    def add_fun(x,y):
        """
        实现两个数相加、并返回合
        """
        return x+y
    
    add_fun = deprecated(add_fun) #包装add_fun函数
    
    def add(x,y):
        """
        实现两个数相加、并返回合
        """
        return x+y    
    
    if __name__=="__main__":
        print(add_fun(1,1))

      调用时的输出

    python3 dc.py
    
    add_fun 函数已经过时
    2

      

      从上面的例子我们看出装饰器并没有什么特别这只不过是一个“返回可调用对象的可调用对象”、下面我们讲一下装饰器的“语法糖衣 @写法”

    def deprecated(fun):
        """deprecated函数会返回一个叫inner的函数、inner函数会返回
        fun调用的结果,与直接调用fun得到值不同的是inner会先打印一行提示
        表明fun已经过时
        """
        def inner(x,y):
            print("{fun.__name__} 函数已经过时".format(fun=fun))
            return fun(x,y)
        return inner
    
    @deprecated        # 使用@写法来实现包装
    def add_fun(x,y):
        """
        实现两个数相加、并返回合
        """
        return x+y
    
    
    def add(x,y):
        """
        实现两个数相加、并返回合
        """
        return x+y    
    
    if __name__=="__main__":
        print(add_fun(1,1))

      从上面可以看出在使用装饰器来处理代码的情况下,add_fun是“封闭”的 ,@写法与上面的函数调用方式下包装add_fun是等价的。输出结果如下

    python3 dc.py
    add_fun 函数已经过时
    2
  • 相关阅读:
    MongoDB数据库性能分析(转)
    C++中拷贝构造函数
    C++中的继承和组合区别使用
    几种调用约定
    动态规划(基础篇)
    C++中的三种继承public,protected,private
    STl中的排序算法
    STL中的常用算法
    C++初始化函数列表
    设计模式之装饰模式(Decorator)
  • 原文地址:https://www.cnblogs.com/JiangLe/p/9309330.html
Copyright © 2011-2022 走看看