Python的装饰器(decorator)是一个很棒的机制,也是熟练运用Python的必杀技之一。装饰器,顾名思义,就是用来装饰的,它装饰的是一个函数,保持被装饰函数的原有功能,再装饰上(添油加醋)一些其它功能,并返回带有新增功能的函数对象,所以装饰器本质上是一个返回函数对象的函数(确切的说,装饰器应该是可调用对象,除了函数,类也可以作为装饰器)。
在编程过程中,我们经常遇到这样的场景:登录校验,权限校验,日志记录等,这些功能代码在各个环节都可能需要,但又十分雷同,通过装饰器来抽象,剥离这部分代码可以很好解决这类场景。
要理解Python的装饰器,首先我们先理解一下Python的函数对象。我们知道,在Python里一切都是对象,函数也不例外,函数是第一类对象(一流的对象),它可以赋值给变量,也可以作为列表的元素,还可以作为参数传递给其它函数。
<强>函数可以被变量引用强>
定义一个简单的函数:
def say_hi (): 打印(“嗨!”) say_hi () #输出:嗨!
个变量say_hi2来引用say_hi函数:
say_hi2=say_hi 打印(say_hi2) #输出:& lt;函数say_hi 0 x7fed671c4378> say_hi2 () #输出:嗨!
上面的语句中say_hi2和say_hi指向了同样的函数定义,二者的执行结果也相同。
<强>函数可以作为参数传递给其它函数强>
def say_more (say_hi_func): 打印(更多的) say_hi_func () say_more (say_hi) #输出: #更多 #嗨 >之前在上面的例子中,我们把say_hi函数当做参数传递给say_more函数,say_hi被变量say_hi_func引用。
<强>函数可以定义在其它函数内部强>
def say_hi (): 打印(“嗨!”) def say_name (): 打印(‘汤姆’) say_name () say_hi () #输出: #你好! #汤姆 say_name() #报的错 >之前上述代码中,我们在say_hi()函数内部定义了另外一个函数say_name () .say_name()只在say_hi函数内部可见(即,它的作用域在say_hi函数内部),在say_hi外包调用时就会出错。
<强>函数可以返回其它函数的引用强>
def say_hi (): 打印(“嗨!”) def say_name (): 打印(‘汤姆’) 返回say_name say_name_func=say_hi () #打印嗨!,并返回say_name函数对象 #并赋值给say_name_func say_name_func () #打印汤姆 >之前上面的例子,say_hi函数返回了其内部定义的函数say_name的引用。这样在say_hi函数外部也可以使用say_name函数了。
前面我们理解了函数,这有助于我们接下来弄明白装饰器。
<>强装饰器(Decorator) 强>
装饰器是可调用对象(可调用的对象),它用来修改函数或类。
可调用对象就是可以接受某些参数并返回某些对象的对象.Python里的函数和类都是可调用对象。函数装饰器,就是接受函数作为参数,并对函数参数做一些包装,然后返回增加了包装的函数,即生成了一个新函数。
让我们看看下面这个例子:
def decorator_func (some_func): #定义另一个包装器函数,修改some_func def wrapper_func (): 打印(“包装器函数开始”) some_func () print(“包装器函数结束”) 返回wrapper_func #包装器函数通过添加一些功能和装饰返回包装器函数 def say_hello (): 打印(“Hello”) say_hello=decorator_func (say_hello) say_hello () #输出: #包装器函数开始 #你好 #包装器函数结束了上面例子中,decorator_func就是定义的装饰器函数,它接受some_func作为参数。它定义了一个wrapper_func函数,该函数调用了some_func但也增加了一些自己的代码。
上面代码中使用装饰器的方法看起来有点复杂,其实真正的装饰器的Python语法是这样的:
深入了解和应用Python装饰器@decorator