本文实例讲述了python自定义装饰器。分享给大家供大家参考,具体如下:
先看一个例子
def德科(函数): 之前打印(“myfunc()被称为”。) 函数() 打印(“myfunc之后()称为”。) 回归函数 @deco def myfunc (): 打印(“myfunc()称为”。) # myfunc=德科(myfunc) #与上面的@deco等价 myfunc () 打印(“* * * * * * * * * * *”) myfunc () >之前会发现,输出为
之前myfunc()调用。
myfunc()调用。 引用>
myfunc()调用。
后myfunc()调用。
myfunc()调用。
* * * * * * * * * * *
这就是说,装饰器里面的东西只调用了一次,为什么呢?
是因为,在myfunc()函数的定义前面加一句@deco, <强>本质上完全等价于在出现def myfunc()后,先将下面所有内容的首地址传递给函数,然后紧接着加上一句myfunc=德科(myfunc)。>强执行这句话,表示func代表了本来定义的myfunc()的函数体,同时函数myfunc()的地址传递给德科()函数,即myfunc→函数,这里就相当于myfunc的值与函数的值完全相同了。然后执行装饰器里面的内容,最后返回给函数,传递给myfunc。接下来在调用myfunc()的时候,打印输出“myfunc()被称为“。第二次调用myfunc()函数的时候,依然只打印输出“myfunc()被称为“。为什么第二次没有执行装饰器里面的内容呢?是因为,myfunc=德科(myfunc)这句话只执行了一次,而这句话,才是真正执行装饰器里面的内容的话。
上面的代码表示,装饰器相当于只对第一次调用他的函数进行了装饰,那么,怎么对每次调用的函数都装饰呢?接着看
def德科(函数): def包装器(* args, * * kwargs): # * args, * * kwargs用于接收func的参数 之前打印(“myfunc()被称为”。) func (* args, * * kwargs) 打印(“myfunc之后()称为”。) 返回包装 @deco def myfunc (a, b): 打印(a + b) # myfunc=德科(myfunc) #与上面的@deco等价 myfunc (1、2) 打印(“* * * * * * * * * * *”) myfunc (3、4) >之前该代码输出结果为
之前myfunc()调用。
myfunc后()调用。 引用>
3
后myfunc()调用。
* * * * * * * * * * *
之前myfunc()调用。
7
我们说了,在myfunc()函数的定义前面加一句@deco, <强>本质上完全等价于在出现def # 63; myfunc()后,先将下面所有内容的首地址传递给函数,然后紧接着加上一句myfunc=德科(myfunc)。>强执行myfunc(1、2)命令的时候,myfunc函数体的地址早已经传递给了德科()函数,返回的是包装。这是myfunc所代表的地址不再是原来的myfunc的地址,而是包装函数的地址。所以,以后凡是出现myfunc()的地方,都是在调用包装()函数。即myfunc(1、2)就是包装器(1、2),所以每次调用myfunc()时候,装饰器里面的内容都会被执行了。而包装()函数体里面的函数,就代表了原来myfunc()的函数体。
怎么进一步理解”<强>在出现def # 63; myfunc()后,先将下面所有内容的首地址传递给func >强”这句话呢?看:
def德科(函数): def包装器(* args, * * kwargs): # * args, * * kwargs用于接收func的参数 打印(“包装器的地址:“哦,包装) func (* args, * * kwargs) 打印(“func的地址:”函数) 返回包装 @deco def myfunc (a, b): 打印(“myfunc的地址:“,myfunc) 打印(a + b) # myfunc=德科(myfunc) #与上面的@deco等价 myfunc (1、2) 打印(“* * * * * * * * * * *”) 打印(“修改后myfunc的地址:“,myfunc) >之前运行结果:
包装的地址:& lt;装饰功能灵活,locals>。包装在0 x0000023aa9ff58c8>
引用>
myfunc的地址:& lt;装饰功能灵活,locals>。包装在0 x0000023aa9ff58c8>
3
func的地址:& lt;函数myfunc 0 x0000023aa9ff5840>
* * * * * * * * * * *
修改后myfunc的地址:& lt;装饰功能灵活,locals>。包装在0 x0000023aa9ff58c8>程序执行到myfunc(1、2)的时候,本质上是在执行包装(1、2),于是先输出包装的地址,再执行func()函数。执行func()函数的时候,输出myfunc()的地址,(可见,此时myfunc的值与包装的是相等),再打印3。当输出func()函数的地址,可见func()函数的地址与myfunc()函数的地址不一样了! ! ! !这就是说,原来定义的myfunc()函数的函数体,已经属于函数了,而不属于myfunc了! !
python自定义装饰器实例详解