views:

194

answers:

6

I'm not quite sure what i mean here, so please bear with me..

In sqlalchemy, it appears i'm supposed to pass an expression? to filter() in certain cases. When i try to implement something like this myself, i end up with:

>>> def someFunc(value):
...    print(value)

>>> someFunc(5 == 5)
True

How do i get the values passed to == from inside the function?

Edit: I'm trying to achieve something like this

 >>> def magic(left, op, right):
 ...    print(left+" "+op+" "+right)

 >>> magic(5 == 5)
 5 == 5

Edit: What about if one of the paramaters was an object?

+1  A: 

You can't. The expression 5 == 5 is evaluated and only then is the result passed to someFunc. The function just gets True (the True object, to be precise), no matter what the expression was.

Edit: Concerning your edit, this question is kind of close.

Edit 2: You could just pass the expression as a string and use eval, like this:

>>> def someFunc(expression_string):
...    print(expression_string, "evaluates to", eval(expression_string))

>>> someFunc("5 == 5")
5 == 5 evaluates to True

Don't know whether that helps you. Keep in mind that eval is a powerful tool, so it's dangerous to pass arbitrary (and possibly even user-generated) input to it.

balpha
A: 

You need to wrap the whole thing as a literal string. You're trying to print that out as a string I assume, correct?

AlbertoPL
A: 

Short answer: You can't. The result of the expression evaluation is passed to the function rather than the expression itself.

Brandon E Taylor
+1  A: 

It appears you can return tuples from eq:

class Foo:
    def __init__(self, value):
            self.value = value

    def __eq__(self, other):
            return (self.value, other.value)


f1 = Foo(5)
f2 = Foo(10)
print(f1 == f2)
Ian P
You can return anything you want from `__eq__`, but returning something that can't be coerced to a bool to compare equality--the purpose of `__eq__`--is a really bad idea.
Glenn Maynard
It's probably bad practice, but this is a theoretical question anyway. More of a "How is this possible?" type thing.
Ian P
SQLalchemy really does something like this? That's one library I won't be touching with a 20-foot steel pole. It's a gross, disgusting hack. (Not attacking you--you're just explaining how they might have done it.)
Glenn Maynard
It is pretty strange. I wonder why they didn't use something like User.name.isEqualToInTheContextOfFilter("ed")
Ian P
Sqlalchmey, sqlobject and pyparsing, both overeride pretty much every operator when dealing with their internal objects. I personally think it makes the user declarations nicer but I understand the disgust.
David Raznick
+7  A: 

You can achieve your example if you make "op" a function:

    >>> def magic(left, op, right):
    ...     return op(left, right)
    ...
    >>> magic(5, (lambda a, b: a == b), 5)
    True
    >>> magic(5, (lambda a, b: a == b), 4)
    False

This is more Pythonic than passing a String. It's how functions like sort() work.

Those SQLAlchemy examples with filter() are puzzling. I don't know the internals about SQLAlchemy, but I'm guessing in an example like query.filter(User.name == 'ed') what's going on is that User.name is a SQLAlchemy-specific type, with an odd implementation of the __eq() function that generates SQL for the filter() function instead of doing a comparison. Ie: they've made special classes that let you type Python expressions that emit SQL code. It's an unusual technique, one I'd avoid unless building something that's bridging two languages like an ORM.

Nelson
Note that there's no need to parenthesize lambda.
Glenn Maynard
True, but putting it in parenthesis makes it easier to read in this case due to the internal parameters of the lambda.
Evan Fosmark
If you like--it's just superfluous parens to me.
Glenn Maynard
Good solution, nice and pythonic.
Ian P
the storm ORM also overloads the == operator
Georg
+3  A: 

An even more pythonic variant of Nelson's solution is to use the operator functions from the operator module in the standard library; there is no need to create your own lambdas.

>>> from operator import eq
>>> def magic(left, op, right):
...   return op(left, right)
... 
>>> magic(5, eq, 5)
True
Ned Deily