我一直在为脚本中的数据库操作编写一些函数,并决定使用函数装饰器来处理数据库连接样板。
一个精简的例子如下所示。
import random
class funcdec(object):
def __init__(self,func):
self.state = random.random()
self.func = func
def __call__(self,*args,**kwargs):
return self.func(self.state,*args,**kwargs)
@funcdec
def function1(state,arg1,**kwargs):
print(state)
@funcdec
def function2(state,arg2,**kwargs):
print(state)
function1(10)
function2(20)
这意味着我可以减少样板量,但每个函数都有不同的状态对象。所以,如果我运行这个,我会得到类似的东西:
python decf.py
0.0513280070328
0.372581711374
我想实现一种方法,使所有修饰函数共享这个状态,我想出了这个。
import random
class globaldec(object):
def __init__(self,func):
self.state = random.random()
def __call__(self,func,*args,**kwargs):
def wrapped(*args,**kawrgs):
return func(self.state,*args,**kwargs)
return wrapped
@globaldec
class funcdec(object):
pass
@funcdec
def function1(state,arg1,**kwargs):
print(state)
@funcdec
def function2(state,arg2,**kwargs):
print(state)
function1(10)
function2(20)
现在,当我运行它时,每个应用程序只创建一次状态对象,并且所有修饰函数的状态都相同,例如:
python decg.py
0.489779827086
0.489779827086
直觉上这对我有意义,因为globaldec
只为函数修饰器的所有实例初始化一次。
但是,我对这里发生的事情有点朦胧,以及funcdec
对象似乎不再被初始化或调用的事实。
答案 0 :(得分:3)
您已创建装饰工厂;一个可调用的对象,用于生成装饰器。在这种情况下,当使用func
类作为装饰器时,您忽略<{1}} globaldec.__init__()
funcdec
参数globaldec
(原始globaldec
类对象)。您改为将其替换为function1
类的实例,然后将其用作function2
和@globaldec
的真正装饰器。
那是因为装饰者只是语法糖;应用于class funcdec:
行的class funcdec(object):
pass
funcdec = globaldec(funcdec)
装饰器可以表示如下:
funcdec
所以globaldec
该类被func
的实例取代。
我没有使用类,而是使用函数;像state
和import random
def funcdec(func):
state = random.random()
def wrapper(*args, **kwargs):
return func(state, *args, **kwargs)
return wrapper
这样的状态会成为封闭。
然后您的原始装饰者可以这样写:
funcdec()
因此,当Python将其应用为装饰器时,wrapper
将返回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)
只需创建一次装饰器:
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
现在将package main
//#cgo pkg-config: gtk+-3.0
//#include "ui.h"
import "C"
func CInit() {
C.Init(nil, 0)
}
func CMain() {
C.Main()
}
func CShowWindow() {
C.ShowWindow()
}
func main() {
CInit()
CShowWindow()
CMain()
}
称为共享值。