Python“;“多级装饰器”这是怎么回事?

Python“;“多级装饰器”这是怎么回事?,python,decorator,python-decorators,Python,Decorator,Python Decorators,我一直在用脚本编写一些用于数据库操作的函数,并决定使用函数装饰器来处理db连接样板文件 下面显示了一个简化的示例 函数装饰器: 这意味着我可以减少样板文件的数量,但每个函数有一个不同的状态对象。因此,如果我运行此程序,我会得到如下结果: python decf.py 0.0513280070328 0.372581711374 我想实现一种方法,让所有修饰函数共享这个状态,我想到了这个 装饰功能装饰器: 现在,当我运行此程序时,每个应用程序只创建一次状态对象,并且所有修饰函数的状态都相同,例

我一直在用脚本编写一些用于数据库操作的函数,并决定使用函数装饰器来处理db连接样板文件

下面显示了一个简化的示例

函数装饰器: 这意味着我可以减少样板文件的数量,但每个函数有一个不同的状态对象。因此,如果我运行此程序,我会得到如下结果:

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
    引用为共享值