python函数装饰器,可以通过实例属性、全局变量、非局部变量和函数属性,来保存被装饰函数的状态信息。
描述
通过装饰器统计函数调用次数,并且用打印来跟踪调用记录。
此装饰器用类的__call__()方法来实现。
(1) 装饰器返回实例对象;
(2) 构造函数初始化调用次数为0,记录传入的被装饰函数;
(3) 重载__call__()方法,每次调用计增一次调用次数,并且调用被装饰器函数和打印调用信息;
(4) 返回的实例对象赋值给原函数名;
(5) 调用原函数,相当于实例名(),而括号运算符自动调用__call__()方法,从而达到统计调用次数的功能。
示例
>>> class CountTrace:
def __init__(self,func):
self.calls=0
self.func=func
#实例名()运算,自动调用__call__
def __call__(self,*args):
self.calls+=1
print('调用{}{}次'.format(self.func.__name__,self.calls))
self.func(*args)
>>> @CountTrace
def testct(x):
print(x)
# testct 为 CountTrace 的实例对象
>>> testct
<__main__.CountTrace object at 0x00000173D57DFDF0>
>>> for i in range(5):
testct(i+1)
调用testct1次
1
调用testct2次
2
调用testct3次
3
调用testct4次
4
调用testct5次
5
>>> testct.calls
5
python的实例属性、全局变量、非局部变量和函数属性,可以保存被装饰函数的状态信息。
描述
通过类实例属性来保存被装饰函数的状态信息。
(1) 将被装饰函数赋值保存到类实例属性self.func;
(2) 每装饰一个函数就创建一个类实例;
(3) 被装饰的多个不同函数,相当于多个不同的类实例,保存各自的状态信息;
示例
>>> class CountTrace:
def __init__(self,func):
self.calls=0
self.func=func
#实例名()运算,自动调用__call__
def __call__(self,*args,**kargs):
self.calls+=1
print('调用{}{}次'.format(self.func.__name__,self.calls))
return self.func(*args,**kargs)
>>> @CountTrace
def testct(x):
print(x)
>>> @CountTrace
def testsquare(x):
print(x**2)
>>> testct(2)
调用testct1次
2
>>> testsquare(3)
调用testsquare1次
9
描述
通过嵌套函数的global来保存被装饰函数的状态信息,实现被装饰函数统一计数。
(1) 定义全局比变量calls;
(2) 嵌套函数声明全局变量calls,并进行递增;
(3) 返回的wrapper赋值给各自被装饰的函数,并且共用全局变量calls,所以多个不同的被装饰函数,共用一个计数器;
示例
>>> calls=0
>>> def counttrace(func):
def wrapper(*args,**kargs):
global calls
calls+=1
print('调用{}{}次'.format(func.__name__,calls))
return func(*args,**kargs)
return wrapper
>>> @counttrace
def testct(x):
print(x)
>>> @counttrace
def testsquare(x):
print(x**2)
>>> testct('梯阅线条')
调用testct1次
梯阅线条
# 多个被装饰的函数共用一个计数器
>>> testsquare(3)
调用testsquare2次
9
global
描述
函数主体内部声明变量为global,则可以对函数外部的变量进行修改。
示例
>>> vg='tyxt.work'
>>> def noglobal():
vg='梯阅线条'
>>> def hvglobal():
global vg
vg='梯阅线条'
>>> vg
'tyxt.work'
>>> noglobal()
>>> vg
'tyxt.work'
>>> hvglobal()
>>> vg
'梯阅线条'
描述
通过嵌套函数的nonlocal来保存被装饰函数的状态信息,实现对被装饰函数各自计数。
(1) 外部函数初始化变量calls=0;
(2) 嵌套函数声明nonlocal变量calls,并进行递增;
(3) 返回的wrapper赋值给各自被装饰的函数,并且使用各自的calls,多个不同的被装饰函数,各用一个计数器;
示例
>>> def counttrace(func):
calls=0
def wrapper(*args,**kargs):
nonlocal calls
calls+=1
print('调用{}{}次'.format(func.__name__,calls))
return func(*args,**kargs)
return wrapper
>>> @counttrace
def testct(x):
print(x)
>>> @counttrace
def testsquare(x):
print(x**2)
>>> testct('梯阅线条')
调用testct1次
梯阅线条
# 多个被装饰的函数各用一个计数器
>>> testsquare(3)
调用testsquare1次
9
nonlocal
描述
python通过nonlocal修改嵌套函数的外部函数的变量。
示例
>>> def f1():
s='tyxt.work'
def f2():
s='梯阅线条'
print('f2=',s)
f2()
print('f1=',s)
>>> f1()
f2= 梯阅线条
f1= tyxt.work
>>> def f1():
s='tyxt.work'
def f2():
# 通过nonlocal直接修改嵌套作用域的变量
nonlocal s
s='梯阅线条'
print('f2=',s)
f2()
print('f1=',s)
>>> f1()
f2= 梯阅线条
f1= 梯阅线条
描述
通过嵌套函数属性来保存被装饰函数的状态信息,实现对被装饰函数各自计数。
(1) 嵌套函数内部,通过wrapper.calls+=1,进行递增;
(2) 嵌套函数wrapper后面,对calls进行初始化;
(3) 返回的wrapper赋值给各自被装饰的函数,并且使用各自的calls,所以多个不同的被装饰函数,各用一个计数器;
示例
>>> def counttrace(func):
def wrapper(*args,**kargs):
wrapper.calls+=1
print('调用{}{}次'.format(func.__name__,wrapper.calls))
return func(*args,**kargs)
# 定义函数 wrapper 后,再进行属性赋值
wrapper.calls=0
return wrapper
>>> @counttrace
def testct(x):
print(x)
>>> @counttrace
def testsquare(x):
print(x**2)
>>> testct('梯阅线条')
调用testct1次
梯阅线条
# 多个被装饰的函数各用一个计数器
>>> testsquare(3)
调用testsquare1次
9