如何使用类方法来修饰其他类方法?

时间:2017-02-20 04:08:49

标签: python decorator

在设计类时,我发现在类方法中,每次调用类方法时都会调用重复的步骤。例如:

class Queue(object):
    def __init__(self):
        self.connection = Connection()

    def create(self, name):
        self.probe = self.connection.plug()
        self.probe.create(name)
        self.probe.unplug()

    def delete(self, name):
        self.probe = self.connection.plug()
        self.probe.delete(name)
        self.probe.unplug()

并且有很多方法需要类似的步骤才能插入'并且'拔掉' '探测'。在这个设计中,我们需要“插入”。并且'拔掉' '探测'每次我们执行操作。

因此,我正在考虑通过装饰器包装这些函数,以使代码看起来不那么重复。

class Queue(object):
    def __init__(self):
        self.connection = Connection()

    def _with_plug(self, fn):
        def wrapper(*args, **kwargs):
            self.probe = self.connection.plug()
            fn(*args, **kwargs)
            self.probe.unplug()

    @_with_plug        
    def create(self, name):
        self.probe.create(name)

    @_with_plug
    def delete(self, name):
        self.probe.delete(name)

但这种策略不起作用。在调用方法之前和之后,如何使用类中的方法来装饰其他方法来执行此类操作?

2 个答案:

答案 0 :(得分:1)

对我来说似乎有点混乱:

文件deco.py,说

def _with_plug(fn): # decorator takes exactly one argument, the function to wrap
    print("wrapping", fn.__name__)
    def wrapper(self, *args, **kwds):
        print("wrapper called")
        self.probe = [self.connection, ".plug()"]
        fn(self, *args, **kwds)
        self.probe.append(".unplug()")
    return wrapper # decorator must return the wrapped function


class Queue(object):
    def __init__(self):
        self.connection = "Connection()"

    @_with_plug
    def create(self, name):
        self.probe.append("create(name)")

    @_with_plug
    def delete(self, name):
        self.probe.append("delete(name)")

检查:

>>> import deco
wrapping create
wrapping delete
>>> q = deco.Queue()
>>> q.create("name")
wrapper called
>>> q.probe
['Connection()', '.plug()', 'create(name)', '.unplug()']

观察装饰器函数是在待包装函数的 definition 时间调用的,即在类定义完成之前和创建第一个实例之前很久。因此,您无法以您尝试的方式引用self

答案 1 :(得分:0)

您应该在类主体之外定义装饰器函数,并且装饰器函数应该返回包装函数以使其工作。类似的东西:

def _with_plug(fn):
    def wrapper(self, *args, **kwargs):
        self.probe = self.connection.plug()
        fn(self, *args, **kwargs)
        self.probe.unplug()
    return wrapper


class Queue(object):
    def __init__(self):
        self.connection = Connection()

    @_with_plug        
    def create(self, name):
        self.probe.create(name)

    @_with_plug
    def delete(self, name):
        self.probe.delete(name)