Python“;“多级装饰器”这是怎么回事?
我一直在用脚本编写一些用于数据库操作的函数,并决定使用函数装饰器来处理db连接样板文件 下面显示了一个简化的示例 函数装饰器: 这意味着我可以减少样板文件的数量,但每个函数有一个不同的状态对象。因此,如果我运行此程序,我会得到如下结果:Python“;“多级装饰器”这是怎么回事?,python,decorator,python-decorators,Python,Decorator,Python Decorators,我一直在用脚本编写一些用于数据库操作的函数,并决定使用函数装饰器来处理db连接样板文件 下面显示了一个简化的示例 函数装饰器: 这意味着我可以减少样板文件的数量,但每个函数有一个不同的状态对象。因此,如果我运行此程序,我会得到如下结果: python decf.py 0.0513280070328 0.372581711374 我想实现一种方法,让所有修饰函数共享这个状态,我想到了这个 装饰功能装饰器: 现在,当我运行此程序时,每个应用程序只创建一次状态对象,并且所有修饰函数的状态都相同,例
python decf.py
0.0513280070328
0.372581711374
我想实现一种方法,让所有修饰函数共享这个状态,我想到了这个
装饰功能装饰器:
现在,当我运行此程序时,每个应用程序只创建一次状态对象,并且所有修饰函数的状态都相同,例如:
python decg.py
0.489779827086
0.489779827086
直观地说,这对我来说是有意义的,因为对于函数decorator的所有实例,globaldec
只初始化一次
然而,我有点不清楚这里到底发生了什么,而且funcdec
对象似乎不再被初始化或调用
问题:
globaldec
类作为装饰器时,您将忽略globaldec.\uuuu init\uuuu()
(原始的funcdec
类对象)的func
参数。您将其替换为globaldec
类的一个实例,然后将其用作function1
和function2
的真正装饰器
那是因为装饰者只是语法上的糖;应用于类funcdec:
行的@globaldec
装饰器可以这样表示:
class funcdec(object):
pass
funcdec = globaldec(funcdec)
import random
def funcdec(func):
state = random.random()
def wrapper(*args, **kwargs):
return func(state, *args, **kwargs)
return wrapper
因此,funcdec
该类被一个globaldec
的实例替换
我不使用类,而是使用函数;类似于func
和state
的状态成为闭包
你最初的装饰师可以这样写:
class funcdec(object):
pass
funcdec = globaldec(funcdec)
import random
def funcdec(func):
state = random.random()
def wrapper(*args, **kwargs):
return func(state, *args, **kwargs)
return wrapper
因此,当Python将其作为装饰程序应用时,funcdec()
返回包装器
函数,替换原来的function1
或function2
函数,并将其替换为该函数对象。调用wrapper()
然后依次通过func
闭包调用原始函数对象
globaldec
版本只是增加了一层;外部函数生成装饰器,将闭包移出一步:
import random
def globaldec():
state = random.random()
def funcdec(func):
def wrapper(*args, **kwargs):
return func(state, *args, **kwargs)
return wrapper
return funcdec
只需创建一次装饰器:
funcdec = globaldec()
@funcdec
def function1(state,arg1,**kwargs):
print(state)
@funcdec
def function2(state,arg2,**kwargs):
print(state)
另一种模式是将状态存储为全局(您可以直接在decorator函数上执行此操作:
import random
def funcdec(func):
if not hasattr(funcdec, 'state'):
# an attribute on a global function is also 'global':
funcdec.state = random.random()
def wrapper(*args, **kwargs):
return func(funcdec.state, *args, **kwargs)
return wrapper
现在您不再需要生成专用的装饰器对象,wrapper
现在将funcdec.state
引用为共享值