这句话可以说是对装饰器的功能实现了完美的概括,请自己体会~
我们有了装饰器后就可以在不对原函数有任何改动的情况下,极大的增强了代码的可重用性。以下示例就是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()
装饰器中同样可以传入参数,比如我在上例中加入参数:
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")
装饰器同样可以是一个类,主要依靠其中的__call__
方法来实现。
@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中常用的内置装饰器