没有重复的依赖装饰器

时间:2013-04-16 10:39:36

标签: python decorator python-decorators

在下面的代码中,我编写了依赖装饰器,它只是将一些函数作为参数,并在调用装饰函数之前调用它们。因此,当我使用这个脚本时,我得到输出:

using f
using g
using f
using h

但现在我的问题出现了。怎么做不重复依赖?所以当我使用h()时,f()只会被调用一次?我试图删除重复形式的功能,但例如对于h()它包含wapper和f()。我应该以其他方式收集它们吗?

class depends(object):
    functs = []
    def __init__(self, *f):
        self.functs = []
        for i in f:
            self.functs.append(i)

    def __call__(self, fun):
        def wrapper():
            for i in self.functs:
                i()

            return fun()
        return wrapper

def f():
    print 'using f'

@depends(f)
def g():
    print 'using g'

@depends(g, f)
def h():
    print 'using h'

h()

3 个答案:

答案 0 :(得分:3)

Python已经在其super调用机制中内置了类似的东西。但是,要利用super,您必须将依赖项转换为基类:

def depends(*deps):
    def deco(func):
        def __new__(self):
            super(Dependency, self).__new__(self)
            return func()
        Dependency = type('Dependency', deps, {'__new__': __new__})
        return Dependency
    return deco


@depends(object)
def f():
    print 'using f'


@depends(f)
def g():
    print 'using g'


@depends(g, f)
def h():
    print 'using h'

h()
# using f
# using g
# using h

答案 1 :(得分:1)

您需要全局记住已处理的依赖项,例如在类变量中,请参阅此处的depends.done

class depends(object):
    done = []
    def __init__(self, *f):
        self.functs = f

    def __call__(self, fun):
        def wrapper():
            for i in self.functs:
                if i not in depends.done:
                    i() 
                    depends.done.append(i)

            return fun()
        return wrapper

def f():
    print 'using f'

@depends(f)
def g():
    print 'using g'

@depends(g, f)
def h():
    print 'using h'

h()

答案 2 :(得分:0)

你需要检查是否已经以这种方式修饰了任何依赖函数,并从当前修饰函数的依赖项中排除它们的依赖关系。

这项检查需要递归完成。

如果你也使用其他装饰器会变得更加困难。

我真的很想知道为什么以及如何使用这个结构。