Implementing "and" for Python class?
I have some code similar to this:
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)
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)
I can run filtering tests successfully, for example:
print list(mytable.filter(Row.val3 == 7))
# prints [[1, 2, 7, 'cat'], [7, 7, 7, 'foo']]
print list(mytable.filter(Row.val2 == 2))
# prints [[1, 2, 3, 'hello'], [1, 2, 7, 'cat'], [1, 2, 3, 'hi']]
but when i try to use and
it doesn't work as i would like:
print list(mytable.filter((Row.val3 == 7) and (Row.val2 == 2)))
# this only evaluates the second condition, instead of both conditions, printing:
# [[1, 2, 3, 'hello'], [1, 2, 7, 'cat'], [1, 2, 3, 'hi']]
How can I work and work properly?
source to share
You cannot connect to logical operators and
and or
, because they are short-circuit ; the left expression is evaluated first, and if the result of that expression determines the result, the right expression is never evenly evaluated. The operation returns the value of the last expression evaluated.
In your case, the expression (Row.val3 == 7) and (Row.val2 == 2)
evaluates first (Row.val3 == 7)
, and since this returns an instance without any specific hooks, to say otherwise, this is considered a true value , so the result of the right expression is returned.
Here you can use &
and |
(bitwise AND and OR) , these delegates in and intercepts. This is what ORM libraries like SQLAlchemy do. object.__and__
object.__or__
The corresponding functions and .operator
operator.and_
operator.or_
source to share