Python装饰器

  • 理解:
    装饰器本质上就是一个函数(或者是一个类),它可以在不修改其他函数的代码、调用方式的情况下,为该函数增加功能。故名思义,这样看起来就很好的理解“装饰”二字了,是不是很想我们平时用的装饰物,就好像我们像看一下时间,于是我们带上(使用)了一块手表(装饰器),当我们不需要看时间(该功能)的时候,我们可以将手表(装饰器)摘下(不使用)。同时装饰器在python中也是面向切面的编程(AOP)

以不变应万变,是变也:

这句话可以说是对装饰器的功能实现了完美的概括,请自己体会~

1、基本装饰器

我们有了装饰器后就可以在不对原函数有任何改动的情况下,极大的增强了代码的可重用性。以下示例就是hmh(没错就是我)想要带上一只手表(装饰器)看下当下的时间。
首先,我定义了一个watch(func)装饰器,用以显示当下时间,请注意在装饰器的最后需要返回一个可调用对象(wrapper),不然会出现注释中的异常(程序也可能会正常执行,我踩到的坑。。。)。并且python中的语法糖 @可以极大的精简我们的代码,让装饰器使用起来更加便利,下面示例的执行顺序是这样的:
1、首先定义一个装饰器watch,并且返回一个可调用对象wrapper
2、使用@将其下面定义的函数,作为参数传入之前定义好的装饰器中,并将返回的可调用函数赋值给hmh;
3、定义函数hmh();
4、调用hmh(),将其作为参数传入装饰器中,然后执行函数wrapper,将现在的时间打印出来,接着执行函数hmh;

   import datetime


   def watch(func):
   
       def wrapper():
           print(datetime.datetime.now())
           return func()
       return wrapper      # 应该在这一步返回一个可调用对象,否则会报错-'NoneType' object is not callable
   
   
   @watch  # hmh = watch(hmh)
   def hmh():
       print("I am hmh")
       # return None
   
   hmh()

2、可传参装饰器

装饰器中同样可以传入参数,比如我在上例中加入参数:

  import datetime
  
  
  def watch(func):
  
      def wrapper(*args):
          print(datetime.datetime.now())
          return func(*args)
      return wrapper      # 应该在这一步返回一个可调用对象,否则会报错-'NoneType' object is not callable
  # return None
  
  
  @watch
  def hmh(name):
      print("I am %s" % name)
      # return None
  
  hmh("Pluto")

3、装饰器类

装饰器同样可以是一个类,主要依靠其中的__call__方法来实现。

4、内置装饰器

  • @property
    属性,使得调用类中的方法就好像是在调用静态属性一样,简单来说就是在调用函数时候不需要(),对复杂场景下的访问形式形式进行了规范化的统一(遵循了统一访问的原则)。
    下面的示例中,因为使用了装饰器@property,在最后一个print语句中就不再需要(),而是像倒数第二条print语句调用的静态属性一样来对动态的方法进行调用。
   class Pluto(object):
       def __init__(self, name):
           self.name = name
       
       @property
       def say_hello(self):
           print('Hello')
   
   
   pluto = Pluto("hmh")
   print(pluto.name)   # 通过实例来进行调用
   print(pluto.say_hello)  # 通过类名直接调用
   >>>
   hmh
   Hello
  • @staticmethod
    静态方法,不需要将类实例化,可以使用类名直接进行调用,并且不需要表示自身的参数(比如self),达到将函数功能与实例解绑的效果。
   class Pluto(object):
       def __init__(self, name):
           self.name = name
   
       @staticmethod
       def say_hello():
           return 'Hello'
   
   
   pluto = Pluto("hmh")
   print(pluto.name)   # 通过实例来进行调用
   print(Pluto.say_hello())    # 通过类名直接调用
   >>>
   hmh
   Hello
   ```
 
* `@classmethod`
 类方法,其第一个参数是一个类,是将类本身作为操作的方法,类方法被哪个类调用,就传入哪个类作为第一个参数进行操作。同样不需要将实例化就可以直接使用“类名.方法名”对类中的函数进行调用,需要表示自身的参数`cls`。
 下面的示例中可以看出,类方法`say_hello`被类`ENG`调用,就将类`ENG`作为第一个参数传入`sentence`。
 
```python
   class Hello(object):
       name = "hmh"
   
       @classmethod
       def say_hello(self, sentence):
           print("%s %s" % (sentence, self.name))
           # return 'Hello'
   
   
   class CHN(Hello):
       pass
   
   
   class ENG(Hello):
       pass
   
   
   pluto = CHN()
   pluto.say_hello("好久不见")     # 通过实例进行调用
   
   ENG.say_hello("long time no see")    # 通过函数名直接进行调用
   >>>
   好久不见 hmh
   long time no see hmh
  • 关于装饰器的进阶知识,可参考:

理解 Python 装饰器就看这一篇

Python装饰器与面向切面编程

[Python] 对 Python 装饰器的理解的一些心得分享出来给大家参考

python中常用的内置装饰器

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值