首先,python装饰器的作用是:在不改变原有函数实现的前提下,给此函数增加一些额外的功能(在原有函数调用之前或者调用之后),好像给原有函数加上了一个装饰的壳子。
通过一个例子解释python装饰器:
# -*- coding:utf8 -*-
def w1(func):
def inner(*args,**kwargs):
print 'w1'
func(*args,**kwargs)
print func
return inner
def w2(func):
print func
def inner(*args,**kwargs):
print 'w2'
func(*args,**kwargs)
return inner
def w3(func):
print func
def inner(*args,**kwargs):
print 'w3'
func(*args,**kwargs)
return inner
@w3
@w2
@w1
def f1(arg1,arg2,arg3):
print 'f1'
f1(1,2,3)
以上是python多个装饰器使用的例子,目的是为了更好说明装饰器、以及装饰器链的使用,装饰器函数的调用顺序等等。
那么,在使用三个装饰器装饰f1函数,会怎么执行呢,结果如何呢?
首先需要明确一个概念,函数和函数的调用。
以上代码中:f1、w1、w2、w3、inner等都是函数,函数其实在内存中就是一个地址。f1(1,2,3)是函数调用。很简单的问题,很容易理解。
第二个概念:语法糖。(@函数名来装饰函数名) 只举一个例子:
@w1
def f1(arg1,arg2,arg3):
print 'f1'
以上代码相当于
def f1(arg1,arg2,arg3):
print 'f1'
f1 = w1(f1)
注意:f1 = w1(f1) 中,作为参数的f1和返回的f1 已经不是同一个f1了。
好,先看看执行结果:
疑问1:w1 w2 w3三个装饰器的执行顺序是怎么样的?
疑问2:为什么调用了三次装饰器,只调用了一次f1,不应该每调用一次w就调用一次f1吗?
第一个疑问:多个装饰器的调用顺序是自下往上,但是运行时的执行顺序是自上往下!其实只需要记住调用顺序是自下往上,执行顺序可以从调用顺序推出来!同理第二个疑问也可以通过相同办法推出来。
根据以上语法糖的解释,根据自下往上的调用顺序,函数装饰器还可以表示为以下方式:
def f1(arg1,arg2,arg3):
print 'f1'
f1 = w1(f1) #1 把以上f1作为参数传给w1,再把函数返回值传回给f1(相当于给f1赋了新值,新的值为w1的返回值inner)
f1 = w2(f1) #2 把inner(注意,此时f1已经是w1的返回值inner)作为参数传给w2,并且给f1重新赋新值
f1 = w3(f1) #3 把w2的返回值inner作为参数传给f1,并且给f1重新赋值(w3的返回值inner)
为了更加清楚说明,我们翻译如下:
f1 = w1(最初f1)
f1 = w2(w1函数返回值inner)
f1 = w3(w2函数返回值inner)
此时,我们调用函数f1(1,2,3),其实就是调用了w3里面的inner函数。但是给w3传的参数是w2的返回值inner。等调用到w3中func(*args,**kwargs)函数的时候,其实是调用了w2的内层函数inner。以此类推,直到调用w1内部的func(*args,**kwargs)函数的时候,才是调用的最初的f1函数,所以,其实f1函数只调用了一次,而且是按照w3、w2、w1、f1的顺序执行。
以上就是python装饰器的使用。