逻辑组合类实例

2024-09-27 23:28:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一组筛选器对象,它们继承Filter基类的属性

class Filter():
    def __init__(self):
        self.filterList = []

    def __add__(self,f):
        self.filterList += f.filterList  

    def match(self, entry):
        for f in self.filterList:
            if not f(entry):
               return False
        return True

class thisFilter(Filter):
    def __init__(self, args):
        super().__init__()
        ....
        def thisFilterFunc(entry)->bool:
            return True

        self.filterList.append(thisFilterFunc)

此筛选器类由各种函数用于筛选条目

def myfunc(myfilter, arg1, ...):
    ...
    for entry in entries:
        if myfilter.match(entry):
            ... do something

通过添加以下过滤器的实例,可以添加多个过滤器(逻辑和):

bigFilter = filter1 + filter2 + ...

这一切都很好地结合在一起,但我想用一种方法来概括它,以处理更复杂的逻辑约束,例如

bigFilter = (filter1 and filter2) or (filter3 and not filter4)

通过覆盖类的__bool__而不是使用__add__感觉应该可以做到这一点,但类的布尔值仅在给定条目中已知,而在过滤器组装期间不知道

有什么办法可以做到这一点吗?或者有没有更像Python的方法


Tags: inselfadd过滤器forreturnifinit
2条回答

谢谢@njzk2提供的解决方案。在我的代码中,我使用了|&。为了向后兼容,我还保留了.match()而不是使用__call__(),并再次添加了__add__

class Filter:
    def __init__(self, filter: Callable[[Any], bool]):
        self.filter = filter

    def __or__(self, ored: Filter):
        return OrFilter(self, ored)

    def __and__(self, anded: Filter):
        return AndFilter(self, anded)
    
    def __add__(self, added: Filter):
        # self as __and__
        return self.__and__(added)

    def __invert__(self):
        return Filter(lambda x: not self.filter(x))

    def match(self, entry):
        return self.filter(entry)

class AndFilter(Filter):
  def __init__(self, left: Filter, right: Filter):
    self.left = left
    self.right = right

  def filter(self, entry):
    return self.left.filter(entry) and self.right.filter(entry)

class OrFilter(Filter):
  def __init__(self, left: Filter, right: Filter):
    self.left = left
    self.right = right

  def filter(self, entry):
    return self.left.filter(entry) or self.right.filter(entry)

class MyFilter(Filter):
    def __init__(self, args):
        ...
        def ffunc(entry) -> bool:
            ...
        super().__init__(ffunc)

我会选择这样的方式:

class Filter:
  def __init__(self, filter: Callable[[Any], bool]):
    self.filter = filter

  def __add__(self, added: Filter):
    return OrFilter(self, added)

  def __mul__(self, mult: Filter):
    return AndFilter(self, mult)

  def __invert__(self):
    return Filter(lambda x: not self.filter(x))

  def __call__(self, entry):
    return self.filter(entry)

class AndFilter(Filter):
  def __init__(self, left: Filter, right: Filter):
    self.left = left
    self.right = right

  def __call__(self, entry):
    return self.left(entry) and self.right(entry)

class OrFilter(Filter):
  def __init__(self, left: Filter, right: Filter):
    self.left = left
    self.right = right

  def __call__(self, entry):
    return self.left(entry) or self.right(entry)

然后您可以创建过滤器,并将其用作(filterA + ~filterB) * filterC

您可能希望用泛型类型替换该Any,以便您的过滤器知道它在处理什么

相关问题 更多 >

    热门问题