return self 的函数装饰器?

Function decorator that will return self?

我必须遵循 class 这将创建一个对象,该对象具有从 class 变量派生的可链接方法。由于这段代码非常重复,我的挑战是制作一个可以应用于方法 abc 的装饰器。我面临的问题是我似乎无法找到一种方法来构造一个包装器,该包装器将 return 实例 (self)。有没有更好的方法来构造它?

class Test:

    def __init__(self, a, b, c):
        self._a = a
        self._b = b
        self._c = c

        self.call_chain = []


    def a(self, truth):
        def func():
            return self._a == truth
        self.call_chain.append(func)
        return self


    def b(self, truth):
        def func():
            return self._b == truth
        self.call_chain.append(func)
        return self


    def c(self, val):
        def func():
            return self._c == val
        self.call_chain.append(func)
        return self


    def evaluate(self):
        try:
            for f in self.call_chain:
                if f() == False:
                    raise ValueError('False encountered')
        except ValueError:
            self.call_chain.clear()
            return False 
        self.call_chain.clear()
        return True

它像这样链接工作:

c = Test(True, False, 13)
c.a(True).b(False).c(13).evaluate()

诀窍是将函数的参数存储为调用链的一部分。最简单的方法是使用 functools.partial 个对象。

from functools import wraps, partial

def chain(func):
    @wraps(func)
    def wrapper(self, *args, **kwargs):
        suspended = partial(func, self, *args, **kwargs)
        self.call_chain.append(suspended)
        return self
    return wrapper

class Test:
    def __init__(self, a, b, c):
        self.call_chain = []
        self._a = a
        self._b = b
        self._c = c
    @chain
    def a(self, val):
        return self._a == val
    @chain
    def b(self, val):
        return self._b == val
    @chain
    def c(self, val):
        return self._c == val
    def evaluate(self):
        try:
            for f in self.call_chain:
                if f() == False:
                    raise ValueError('False encountered')
        except ValueError:
            self.call_chain.clear()
            return False 
        self.call_chain.clear()
        return True

c = Test(True, False, 13)
c.a(True).b(False).c(13).evaluate()  # True
c.a(True).b(False).c(11).evaluate()  # False