我正在尝试实现contains,它可以用于我的python对象中的任何几个属性。我能够成功实施" =="和大多数其他比较运算符,但" in"给我带来了问题:
import operator
class Comparator:
def __init__(self,fieldName,compareToValue,my_operator):
self.op = my_operator
self.field = fieldName
self.comparedTo = compareToValue
def __call__(self,row):
my_row_val = getattr(row,self.field)
return self.op(my_row_val,self.comparedTo)
class Row:
class RowItem:
def __init__(self,name):
self.name = name
def __eq__(self,other):
return Comparator(self.name,other,operator.eq)
def __contains__(self,other):
return Comparator(self.name,other,operator.contains)
val1 = RowItem("val1")
val2 = RowItem("val2")
val3 = RowItem("val3")
val4 = RowItem("val4")
def __init__(self, val1, val2, val3, val4):
self.val1 = val1
self.val2 = val2
self.val3 = val3
self.val4 = val4
def __str__(self):
return str([self.val1,self.val2,self.val3,self.val4])
def __repr__(self):
return str(self)
class MyTable:
def __init__(self,rows):
self.rows = rows
def filter(self,condition):
for row in self.rows:
if condition(row):
yield row
rows = [Row(1,2,3,"hello"),Row(1,2,7,"cat"),Row(1,2,3,"hi"),Row(7,7,7,"foo")]
mytable = MyTable(rows)
# the line below works fine!
print list(mytable.filter(Row.val3 == 7))
# this line below does not work
print list(mytable.filter("h" in Row.val4))
# TypeError: 'bool' object is not callable
# this line also does not work
print list(mytable.filter(Row.val4 in "hello world"))
# TypeError: 'in <string>' requires string as left operand, not instance
答案 0 :(得分:1)
filter
,你必须传递一个可调用的,而不是一个布尔值row_obj.val4
是类RowItem
的一个实例,而不是__contains__
类的string
方法所期望的字符串答案 1 :(得分:1)
感谢Kevin在评论中回答这个问题。问题是in
(__contains__()
方法)将结果强制转换为布尔值,与其他逻辑比较运算符(__lt__()
,__eq__()
和其他运算符不同。)
似乎这样做的原因主要是向后兼容性。 更多信息: https://mail.python.org/pipermail/python-dev/2013-July/127297.html
解决此问题的一种方法是创建一个新方法(例如,包含_):
尝试这样的事情(这是一个不好的例子,因为包含可以在这段代码中使用:
import operator
class Comparator:
def __init__(self,fieldName,compareToValue,my_operator):
self.op = my_operator
self.field = fieldName
self.comparedTo = compareToValue
def __call__(self,row):
my_row_val = getattr(row,self.field)
return self.op(my_row_val,self.comparedTo)
class Row:
class RowItem:
def __init__(self,name):
self.name = name
def __eq__(self,other):
return Comparator(self.name,other,operator.eq)
def contains_(self,other):
return Comparator(self.name,other,operator.contains)
val1 = RowItem("val1")
val2 = RowItem("val2")
val3 = RowItem("val3")
val4 = RowItem("val4")
def __init__(self, val1, val2, val3, val4):
self.val1 = val1
self.val2 = val2
self.val3 = val3
self.val4 = val4
def __str__(self):
return str([self.val1,self.val2,self.val3,self.val4])
def __repr__(self):
return str(self)
而不是:
def __contains__(self,other):
return Comparator(self.name,other,operator.contains)
当然,在尝试执行“in”时,您需要执行以下操作:
print list(mytable.filter(Row.val4.contains_("h"))) #new way to call in (__contains__)
而不是:
print list(mytable.filter(Row.val4.__contains__("h"))) #old broken way to call in (__contains__)