【问题标题】:Function decorator that will return self?将返回自我的函数装饰器?
【发布时间】:2019-02-14 15:52:03
【问题描述】:

我必须遵循类,该类将使用从类变量派生的可链接方法创建一个对象。由于这段代码非常重复,我的挑战是制作一个可以应用于方法abc 的装饰器。我面临的问题是我似乎无法找到一种方法来构造一个将返回实例的包装器 (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()

【问题讨论】:

  • 你能补充一点信息吗?不清楚为什么你需要一个类或装饰器来完成这个。也许有关您正在处理的实际问题的一些详细信息-也许另一种方法更适合您的情况。

标签: python instance decorator python-decorators self


【解决方案1】:

诀窍是将函数的参数存储为调用链的一部分。最简单的方法是使用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

【讨论】:

  • 这很有趣,我从没想过这样做
猜你喜欢
  • 2020-04-28
  • 2019-11-05
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
  • 2020-12-04
  • 2016-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多