[Baypiggies] overriding boolean and,or operators?

Stephen Lacy slacy at slacy.com
Tue Jul 13 01:01:27 CEST 2010


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
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/baypiggies/attachments/20100712/4da903ad/attachment-0001.html>


More information about the Baypiggies mailing list