[Baypiggies] overriding boolean and,or operators?

Simeon Franklin simeonf at gmail.com
Tue Jul 13 02:47:35 CEST 2010


FWIW - Django's ORM uses the &/| operators to indicate logical "and"
and "or" operators in queries [1]. I like the readability of this
better than the "and_" and "or_" methods.

-regards
Simeon Franklin

[1] http://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects

On Mon, Jul 12, 2010 at 4:01 PM, Stephen Lacy <slacy at slacy.com> wrote:
> Cool, thanks for the great explanation, this makes a lot of sense to me now.
>
> Steve
>
>
> On Mon, Jul 12, 2010 at 3:55 PM, Alex Martelli <aleax at google.com> wrote:
>>
>> `and` and `or` cannot be overridden; they always perform their
>> short-circuit evaluation functionality, no matter what the types on
>> either side.  I understand your surprise, because you think of them as
>> operator, but they're like other keywords such as `lambda`, `if`,
>> `else`... they **control what gets executed, when, and whether the
>> execution happens at all in a certain circumstance**.  Consider:
>>
>> >>> dis.dis(compile('x & y', 'eval', 'eval'))
>>  1           0 LOAD_NAME                0 (x)
>>              3 LOAD_NAME                1 (y)
>>              6 BINARY_AND
>>              7 RETURN_VALUE
>>
>> THIS is the semantics of an actual operator: BOTH operands get
>> evaluated (here, just a LOAD_NAME for each), THEN the operator's code
>> gets control (and can be overridden).  Vs:
>>
>> >>> dis.dis(compile('x and y', 'eval', 'eval'))
>>  1           0 LOAD_NAME                0 (x)
>>              3 JUMP_IF_FALSE            4 (to 10)
>>              6 POP_TOP
>>              7 LOAD_NAME                1 (y)
>>        >>   10 RETURN_VALUE
>>
>> as you see, in bytecode terms, 'and' means JUMP_IF_FALSE -- **no**
>> Python-level code (potentially written by the user in an override)
>> ever executes as part of this "SO-CALLED" operator -- which isn't
>> really one, deep down: it's a *control structure*, like e.g.
>> if/else... which ALSO cannot be overridden of course:
>>
>> >>> dis.dis(compile('x if y else z', 'eval', 'eval'))
>>  1           0 LOAD_NAME                0 (y)
>>              3 JUMP_IF_FALSE            5 (to 11)
>>              6 POP_TOP
>>              7 LOAD_NAME                1 (x)
>>             10 RETURN_VALUE
>>        >>   11 POP_TOP
>>             12 LOAD_NAME                2 (z)
>>             15 RETURN_VALUE
>>
>> Note the extreme similarity of this bytecode to that of the 'and'
>> so-called "operator" -- 'and' is simpler, of course, but very much
>> akin in semantics and implementation.
>>
>> You cannot override 'and' and 'or' just like you cannot override
>> 'if/else' or 'lambda'.
>>
>>
>> Alex
>>
>>
>> On Mon, Jul 12, 2010 at 3:01 PM, Stephen Lacy <slacy at slacy.com> wrote:
>> > Ah, that Infix example is really cute, but not exactly what I was hoping
>> > for.
>> >
>> > I'm actually playing with a bit of trickery -- the __eq__() operator
>> > doesn't
>> > need to return a boolean type (like I think __bool__() does). It can
>> > return
>> > any object.  You can use this trick to make __eq__() into a factory
>> > method
>> > and have it return an object that *represents* the comparison without
>> > actually *doing* the comparison.  This is useful for things like ORM
>> > mappers, where you take the Python expression, traverse the expression
>> > tree,
>> > translate it into SQL, and then execute it.  I'm basing my ideas on the
>> > implementation of Column comparators in SQLAlchemy, which you can see
>> > some
>> > examples of here:
>> > http://www.sqlalchemy.org/docs/sqlexpression.html#operators  But I'm not
>> > working with SQL, I'm trying to do this for another query language.
>> >
>> > I'm having trouble expressing "and" and "or" in a nice Pythonic way, and
>> > if
>> > you look at the SQLAlchemy source, they use and_() and or_() methods,
>> > which
>> > I'd like to try to avoid. I was hoping for some trick, akin to the Infix
>> > thing you mentioned, but that would be a little more pythonic.  (And,
>> > I'm
>> > surprised that you can override pretty much everything except for 'and'
>> > and
>> > 'or')
>> >
>> > Here's a code example I wrote to get the juices flowing:
>> >
>> > http://dpaste.com/217476/
>> >
>> > Line 60 is where things get interesting, I have to use bitwise "and"
>> > instead
>> > of boolean and, because as far as I can tell, there's no override for
>> > boolean and....
>> >
>> > Steve
>> >
>> > On Mon, Jul 12, 2010 at 2:14 PM, Brent Pedersen <bpederse at gmail.com>
>> > wrote:
>> >>
>> >> On Mon, Jul 12, 2010 at 11:21 AM, Stephen Lacy <slacy at slacy.com> wrote:
>> >> > Hi,
>> >> >
>> >> > According to http://docs.python.org/library/operator.html boolean
>> >> > operators
>> >> > ==, <, >, etc. can be overridden via __eq__(), __lt__(), __gt__(),
>> >> > etc.
>> >> >
>> >> > They also mention *bitwise* and/or operators via __and__() and
>> >> > __or__().
>> >> >
>> >> > But, I'd like to override the *boolean* operators 'and' and 'or'.  Is
>> >> > this
>> >> > possible?
>> >> >
>> >> > Background:
>> >> >
>> >> > I'm experimenting with a library that takes a python expression like
>> >> > this:
>> >> >
>> >> > "(a == b) or (c and d)"
>> >> >
>> >> > And instead of evaluating it via the interpreter, creates (and
>> >> > returns)
>> >> > a
>> >> > representation of said boolean decision tree such that it can be
>> >> > evaluated
>> >> > dynamically and/or converted to some other form, like prefix or
>> >> > postfix
>> >> > (this is just an example and for my own exploration and deeper
>> >> > understanding
>> >> > of operator overrides).
>> >> >
>> >> > I can get this to work if I use the syntax "(a == b) | (c & d)" but I
>> >> > would
>> >> > prefer to use the more pythonic and syntactically correct "and" and
>> >> > "or".
>> >> > Is this possible?
>> >> >
>> >> > Steve
>> >> >
>> >> > _______________________________________________
>> >> > Baypiggies mailing list
>> >> > Baypiggies at python.org
>> >> > To change your subscription options or unsubscribe:
>> >> > http://mail.python.org/mailman/listinfo/baypiggies
>> >> >
>> >>
>> >> not quite sure i follow your use-case, but...
>> >> you can also override __nonzero__ which i think is what gets called
>> >> when you use bool(),
>> >> but you'll probably still need a bit more, you can add some sugar using
>> >> this:
>> >> http://code.activestate.com/recipes/384122-infix-operators/
>> >>
>> >> so you'd have your classes implement __bool_or__ (or whatever you want
>> >> to call it) and then use:
>> >>
>> >> OR = Infix(lambda a, b: a.__bool_or__(b))
>> >>
>> >> MyClass(22) |OR| MyClass(0)
>> >>
>> >> where MyClass implements __bool_or__
>> >>
>> >> -brent
>> >
>> >
>> > _______________________________________________
>> > Baypiggies mailing list
>> > Baypiggies at python.org
>> > To change your subscription options or unsubscribe:
>> > http://mail.python.org/mailman/listinfo/baypiggies
>> >
>
>
> _______________________________________________
> Baypiggies mailing list
> Baypiggies at python.org
> To change your subscription options or unsubscribe:
> http://mail.python.org/mailman/listinfo/baypiggies
>


More information about the Baypiggies mailing list