重载Python';在';返回非bool

重载Python';在';返回非bool,python,operator-overloading,Python,Operator Overloading,我试图为类重载in操作符以返回非bool对象,但它似乎还是强制转换。以下是我的用例: class Dataset(object): def __init__(self): self._filters = [] def filter(self, f): self._filters.append(f) return self class EqualFilter(object): def __init__(self, field, val): ...

我试图为类重载
in
操作符以返回非bool对象,但它似乎还是强制转换。以下是我的用例:

class Dataset(object):
  def __init__(self):
    self._filters = []

  def filter(self, f):
    self._filters.append(f)
    return self

class EqualFilter(object):
  def __init__(self, field, val):
    ...

class SubsetFilter(object):
  def __init__(self, field, vals):
    ...

class FilterBuilder(object):
  def __init__(self, field):
    self._field = field

  def __eq__(self, val):
    return EqualFilter(self._field, val)

  def __contains__(self, vals):
    return SubsetFilter(self._field, vals)


veggie = FilterBuilder('veggie')
fruit = FilterBuilder('fruit')
ds = Dataset().filter(veggie == 'carrot').filter(fruit in ['apple', 'orange'])

在代码末尾,
ds
包含一个
EqualFilter
用于
vegige==“carrot”
,以及
True
用于
苹果、橘子中的水果
。有没有办法让DS以“<代码>子设置过滤器< /代码>?< /p> <代码> >列表。首先,
中的
总是将
\uuuuuuuuuuuuuuuuuuuuuu包含的结果强制转换为
bool
,因此您所查找的内容是不可能的。第二个问题是

fruit in ['apple', 'orange']
召唤


中,
的左操作数无法重写运算符,因此这也将挫败您的尝试。

这里真正的问题是,如所述:

对于定义
\uuuu contains\uuuu()方法的用户定义类,
y中的x
当且仅当
y时为真

另请参见和

user2357112的回答比我能更好地解释这一点。您正在调用的是
list.\uuu包含\uuu
,而不是
FilterBuilder.\uu包含\uuu


但为什么会这样呢

好吧,不然怎么行呢

假设[1,2,3]
中的
3被称为
int.\uu包含\uuu
。在{1,2,3}
中的
3以及在我的自定义排序的bintree中的
3也是如此。如何实现
int.\uuuuuuuuuuuuuuuuuuuuuuu(容器)
?当然不是通过在容器上迭代。这将意味着在集合和二叉树中缓慢、彻底地查找内容,这将破坏整个要点。我的bintree类甚至可能不可移植,但可能仍然有成员的概念

但是如果他们调用
list.\uuuu包含\uuuu
set.\uuu包含\uuuu
CustomSortedBintree.\uu包含\uuu
?他们不需要知道int和str,以及你能给他们的所有其他可能的东西吗?不,一点也不。列表只需知道如何比较每个元素的
arg==elem
。集合还需要知道如何调用
哈希(arg)
。bintree还必须知道如何调用
arg
。但要做到这一点,您不需要知道任何关于
arg的类型


你可能想知道如何处理这件事。有两种半通用的解决方案

1:您可以轻松创建
过滤器列表
类。然后,你只要写:

fruit in FilterList('apple', 'orange')
1.5:或者,再多做一点工作,您可以构建一个更通用的“价值持有者”:

2:或者,您可以在
方法中编写一个
FilterBuilder.in。然后你写:

fruit.in_(['apple', 'orange'])
…或者,如果您愿意:

fruit.in_('apple', 'orange')
我见过的大多数库要么提供第二个(sqlalchemy),要么同时提供这两个库,但在它们的教程(appscript)中使用第二个库,尽管“quick lambda”库通常使用第一个库的通用版本

<>但是你应该考虑你自己的用例的权衡。一般来说,第一种方法更容易实现,而且更明确,其优点是子过滤器/子查询可以返回充当
过滤器列表的内容
;第二种方法不那么冗长,而且可以说更容易阅读


如果没有一个是可接受的,您可以考虑编写一个Python类DSL的解析器,而不是试图通过表达式模板从实际Python代码中构建DSL。或者使用类似的方法(我认为它甚至有一个与您正在寻找的类似的示例,以及不需要“const”和friends的quick lambda宏)。

向FilterBuilder添加一个print语句。\uuu包含\uuuuuuuuu确实会导致打印,所以我相当确定FilterBuilder.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu@user1088:来自
FilterBuilder的一些代码路径。\uuuuuuuuuuuuuuuuuuuuuuuuuu。当我实现一个
类打印机(对象)
时,它的
\uuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法中有一个
print
4 in Printer()
打印,但是[1,2,3]
中的
打印机()不打印。@abarnet:error reply target?@user2357112:对不起,是的。顺便说一句,从我所知,不能保证
中的
会将结果强制转换为
bool
。所有相关文档都只是说,如果
\uuuuu包含\uuuuu
返回一个真值,那么它将是一个真值。它可以通过返回bool来实现,但也可以返回值本身。正如您所期望的那样,返回bool,至少Jython和PyPy也是如此,但我仍然认为它取决于实现。@sharth:谢谢您的修复。
fruit.in_(['apple', 'orange'])
fruit.in_('apple', 'orange')