关于Python的修饰器(三)

    Python修饰器的用途可以这样简单的理解,假如我们已经定义了一个对象,如函数F(),并且在代码中完成了相关使用,即已经对函数进行了调用,之后又想对F进行一些修改。方法之一是直接修改F,而不用修改其后对F的调用。但如果想依然保留F的源代码不用修改,在Python中我们可以利用函数是对象可以直接赋值的特性,另外编写一个函数D,进行如下的操作:

       def F:  #F的原始定义,早已经完成

              ...

       def D:  #重新定义一个新函数D,与F类似

              ...

       F=D  #在F原来的调用之前重新将F指向D,以后的调用实际就修改为D了

       ...  #以前的代码,其中有对F的调用

   当然,编写D的另一个好处是如果这种修改是一种对与F类似的系列对象都可能发生的公共的修改,在一次编写D后可以多次使用类似的方法对F1、F2……进行修改,从而提高代码复用率。

    为了方便这种处理,Python修饰器其实只是提供一种语法上看起来简洁的方法,首先定义公共的修改方法D即修饰器,并让其接收被修改对象F等为参数,然后利用@D的修饰器语法形式在定义F系列函数时让其直接完成这种替换与修改,不用再写F=D这一语句,从语法和逻辑上显得更为简洁。不过单从这种使用场景看,个人觉得这种语法上的简洁其实反而不一定让人理解,因此实际上这种方法必须对F等对象在定义时进行修改,如果要改回来,反而不如添加和注释F=D这一语句来得方便。当然,如果有某种条件能够预先明确的知道什么时候需要执行原始的F,什么时候需要对F进行特定的修改,直接在D中根据情况或者返回F本身,或者返回对F的相应修改也是能够提高方便性和代码复用率的。但最为可惜的是由于替换是在定义(或者说编译)时发生的,所以这种应用场景基本没有可能了,因为解释器的条件选择计算仅仅在定义和翻译只进行了一次,其结果是最终修饰后的对象函数实际上只选择了D中的某一个具体的条件选择下的代码对F进行了修改,之后D代码中表面看起来的选择已经不存在了。要想在运行的时候实现动态选择,必须由修改后的函数本身来进行,如下例:

       def D1(f):  #定义修饰器,试图通过判断f()的值来确定对f进行怎样的修改

              if f()>3: return  lambda:2*f()

              else: return  lambda:f()

       @D1

       def F():

              return eval(input('Input:'))

    上述代码看起来想在F中直接由键盘接收一个值并返回,而在D1中根据键盘接收的值是否大于3来判断是否对键盘输入值乘以2。这是一个在运行F时获取键盘输入值并动态返回对输入值响应的过程。但实际上当被修饰函数F一定义完毕,解释器就会立即执行修饰器函数并调用F从键盘获得一个输入值,若这时的输入值大于3,则函数F被固定的修改为返回键盘值的2倍,否则被固定为返回键盘输入值。此后在你运行F函数输入的值是否大于3,结果都被固定下来了。

    要想具有动态效果,其条件判断必须由修改后的函数来执行,如下例:

       def D2(f):  #定义修饰器,由修饰器修改的函数来完成条件判断,获得动态效果

              def dF():

                     v=eval(input('Input:'))

                     if v>3:  return 2*v

                     else:  return v

              return dF

       @D2

       def F():

              return eval(input('Input:'))

    上述修饰器函数实际上是完全重现了原F函数的输入功能,并根据输入值对其原有的返回值功能进行了修饰修改,或者说由dF函数完全取代了F函数,其条件判断实际是在dF中执行的,所以才能实现动态的判断,获得正确的功能。

    其实Python语言本身倒是充分利用了这种公共抽象修改的特点,实现了很多其内部的语法特征。如Python类的方法分为由实例个体拥有的个体方法(一般的方法),由类拥有的类方法,以及静态方法。Python对类方法和静态方法的实现都是通过其内建的修饰器函数classmethod(cls,function)、staticmethod(function)并使用修饰器语法@classmethod和@staticmethod实现的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值