所谓装饰就是在被装饰的函数执行前/后执行一些额外的功能。
装饰器是用来对“装饰”进行封装的一种手段,让在被装饰函数执行前/后被执行的代码更简洁,复用性更高,对原来的代码变动最少。这一点同设计模式中的装饰器概念类似。面向方面(切面)编程中应用很多。
装饰器的实现依赖于Python语言的三个特征:1.函数参数;2函数返回值;3函数内嵌套定义函数。
装饰器封装代码的思路:创建一个函数返回一个函数,返回的函数对新增代码和被装饰的函数进行封装。通过调用这个返回的函数实现对新增代码和被装饰函数的调用。 可以将返回的函数赋值给和被装饰的函数同名的变量。 调用被装饰函数的代码不需要改动而实现新增功能。
Python的装饰器是一个函数,在该函数中创建并返回一个可以执行原函数和新增代码的函数。如下例:
def butter(func):
def wrapper():
print("*******Butter********")
func()
return("Spreaded butter on bread")
return wrapper
def bread():
print('=======Bread=========')
bread=butter(bread)
Status=bread()
print(Status)
*******Butter********
=======Bread=========
Spreaded butter on bread
上面代码中我们需要手动的给被装饰的函数重新赋值:bread=butter(bread). Python对此提供了一个简便的语法(语法糖):在被装饰的函数定义前用@指明装饰函数,如:@butter,就可以直接调用被装饰函数而不需要重新赋值。上面代码等价下面代码:
def butter(func):
def wrapper():
print("*******Butter********")
func()
return("Spreaded butter on bread")
return wrapper
@butter
def bread():
print('=======Bread=========')
Status=bread()
print(Status)
以上是自定义的装饰器,Python内部预定义了三个装饰器:staticmethod,classmethod和property
staticmethod:用于定义静态方法。 静态方法中只能访问类的其他类方法,静态方法和类变量,并且需要用加类名限定,形如:<ClassName>.<StaticMethodName|ClassMethodName|ClassVarable>。静态方法通过类名调用,不需要实例化对象,所以不需要传入self作为第一参数。类对象也能直接调用该类的静态方法。
classmethod:用于定义类方法。 类方法内部只能访问类的其他类方法,静态方法和类变量,并且需要用加类名限定,形如:<ClassName>.<StaticMethodName|ClassMethodName|ClassVarable> 或者cls.<StaticMethodName|ClassMethodName|ClassVarable>。类方法通过类名调用,不需要实例化对象,但因为需要访问类中其他类方法,变量,所以虽然不需要传入self作为第一参数,但要把cls作为第一参数。类对象也能直接调用该类的类方法。
下面代码对上述定义进行演示:
class voice():
@staticmethod
def speak(lang):
return lang
@classmethod
def setmsg(cls,lang):
lang=voice.speak(lang)
if lang=="CN":
return "你好"
elif lang=="EN":
return "Hello"
else:
return "*&@#$!~$#%#&%"
@classmethod
def sayHello(cls,lang):
msg=cls.setmsg(lang)
print(msg)
voice.sayHello("EN")
voice.sayHello("CN")
----输出----
Hello
你好
property用于将无参数且返回单值的方法定义为属性,可以简化访问。
当一个方法被确定为property后,相应的<PropertyName>.getter,<PropertyName>.setter和<PropertyName>.deleter三个装饰器便可用了。这三个装饰器分别对应属性的写,读,删除操作。property修饰的方法是默认的getter,入过定义了新的getter 则默认的getter失效。如下代码示例:
class car():
__color="black"
@property
def color(self):
return self.__color
@color.getter
def color(self):
return "color"
@color.setter
def color(self, clr):
self.__color=clr
@color.deleter
def color(self):
del self.__color
c=car()
c.color="red"
print(c.color)
----输出----
color # 如果没有@color.getter装饰器,则会返回: red.