为 Python class 实施 "and"?
Implementing "and" for Python class?
我有类似的代码:
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)
我可以成功运行过滤测试,例如:
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']]
但是当我尝试使用 and
时,它无法正常工作:
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']]
如何让 和 正常工作?
您不能挂接到 and
和 or
逻辑运算符,因为它们 short-circuit;左边的表达式首先被求值,如果该表达式的结果决定了结果,则右边的表达式永远不会被求值。操作 returns 计算的最后一个表达式的值。
在你的例子中,(Row.val3 == 7) and (Row.val2 == 2)
表达式首先计算 (Row.val3 == 7)
,并且 returns 一个没有任何特定钩子的实例,否则就是 considered a true value,因此返回右侧表达式的结果。
您可以使用&
and |
(bitwise AND and OR) operators here, these delegate to the object.__and__
and object.__or__
钩子。这就是像 SQLAlchemy 这样的 ORM 库所做的。
对应的operator
函数为operator.and_
and operator.or_
.
我有类似的代码:
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)
我可以成功运行过滤测试,例如:
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']]
但是当我尝试使用 and
时,它无法正常工作:
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']]
如何让 和 正常工作?
您不能挂接到 and
和 or
逻辑运算符,因为它们 short-circuit;左边的表达式首先被求值,如果该表达式的结果决定了结果,则右边的表达式永远不会被求值。操作 returns 计算的最后一个表达式的值。
在你的例子中,(Row.val3 == 7) and (Row.val2 == 2)
表达式首先计算 (Row.val3 == 7)
,并且 returns 一个没有任何特定钩子的实例,否则就是 considered a true value,因此返回右侧表达式的结果。
您可以使用&
and |
(bitwise AND and OR) operators here, these delegate to the object.__and__
and object.__or__
钩子。这就是像 SQLAlchemy 这样的 ORM 库所做的。
对应的operator
函数为operator.and_
and operator.or_
.