将逻辑运算符(和部分表达式)传递给函数参数Python

时间:2015-05-05 18:58:12

标签: python sqlalchemy logical-operators

在SQLAlchemy中,可以执行以下操作:

mytable.query.filter(mytable.some_col < 5).all()

我如何实现类似的东西?我希望开发人员用户能够将逻辑操作传递给函数。这是一个例子:

class row_obj:
    def __init__(self, val1, val2, val3, val4):
        self.val1 = val1
        self.val2 = val2
        self.val3 = val3
        self.val4 = val4
    def __repr__(self):
        return str(self.val1)+","+str(self.val2)+","+str(self.val3)+","+str(self.val4)

class table_obj:
    """ takes a list of row_objs """
    def __init__(self, rows):
        self.rows = rows #rows is a list of row_obj 
    def __repr__(self):
        return "\n".join([str(row) for row in self.rows])
    def filter(self, condition):
        # I would like to return all rows which meet the condition here
        return table_obj([row for row in self.rows if condition])

a = table_obj([ row_obj(1,2,3,4),
      row_obj(5,6,7,8),
      row_obj(2,4,6,8),
      row_obj(5,2,7,4)])

print a.filter(row_obj.val3 == 7)
#should return 
#5,6,7,8
#5,2,7,4

3 个答案:

答案 0 :(得分:4)

正如您所提到的,SQLAlchemy允许使用以下表达式:

mytable.query.filter(mytable.some_col < 5).all()

这是可能的,因为mytable.some_col为每个返回一些其他对象的逻辑运算符实现了魔术方法(在本例中为__lt__)。所以操作符并没有真正传入。在我的应用程序中定义了一个User对象,可以通过以下方式看到:

>>> User.first_name == 'John'
<sqlalchemy.sql.elements.BinaryExpression object at 0x10f0991d0>

你可以做同样的事情来达到同样的效果。

答案 1 :(得分:3)

您可以传递lambda函数来执行此操作;然后将它们作为任何正常函数处理:

>>> def someFunction (condition):
        return [row for row in range(100) if condition(row)]
>>> someFunction(lambda x: x % 11 == 0)
[0, 11, 22, 33, 44, 55, 66, 77, 88, 99]
>>> someFunction(lambda x: x % 23 == 0)
[0, 23, 46, 69, 92]

当然,不是像我的例子那样传递一个简单的int对象,你也可以传递一个更复杂的对象,并对它做一些更复杂的检查,例如:

lambda x: x.someOtherProperty.evenAMethod('with a parameter') > 42

对于您问题中的具体示例:更改table_obj.filter以调用condition参数,并将该行作为参数:

def filter(self, condition):
    return table_obj([row for row in self.rows if condition(row)])
    #                                                      ^^^^^
    #                                                     new part

然后,您可以使用lambda表达式指定过滤器:

 print a.filter(lambda row_obj: row_obj.val3 == 7)
 #              ^^^^^^^^^^^^^^^
 #                 new part

这样可以完全所需的结果。

答案 2 :(得分:1)

不幸的是,这有点不重要,实施起来很糟糕,但你可以做这样的事情

 public override void OnActionExecuting(ActionExecutingContext context)
 {
    // SET A COOKIE

    base.OnActionExecuting(context);
 }

这不仅仅是让你了解你必须采取的路径,这将是非平凡的(并且有点粗略......)