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?

+3


source to share


1 answer


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_

+3


source







All Articles