逻辑组合 class 个实例
Logically combine class instances
我有一组过滤器对象,它们继承了 Filter
基础 class
的属性
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)
这个过滤器 classes 被各种函数用来过滤条目
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)
感觉这应该可以通过覆盖 class 的 __bool__
而不是使用 __add__
来实现,但是 class 的布尔值只知道一个给定的条目,而不是在过滤器的组装过程中。
任何想法如何使这成为可能?或者是否有更 pythonic 的方法来做到这一点?
我会选择这样的东西:
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
替换为通用类型,以便您的过滤器知道它在处理什么。
谢谢@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)
我有一组过滤器对象,它们继承了 Filter
基础 class
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)
这个过滤器 classes 被各种函数用来过滤条目
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)
感觉这应该可以通过覆盖 class 的 __bool__
而不是使用 __add__
来实现,但是 class 的布尔值只知道一个给定的条目,而不是在过滤器的组装过程中。
任何想法如何使这成为可能?或者是否有更 pythonic 的方法来做到这一点?
我会选择这样的东西:
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
替换为通用类型,以便您的过滤器知道它在处理什么。
谢谢@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)