[Baypiggies] overriding boolean and,or operators?
aleax at google.com
Tue Jul 13 00:55:38 CEST 2010
`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)
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)
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)
7 LOAD_NAME 1 (x)
>> 11 POP_TOP
12 LOAD_NAME 2 (z)
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'.
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
> 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
> Here's a code example I wrote to get the juices flowing:
> 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....
> 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
>> 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__
> Baypiggies mailing list
> Baypiggies at python.org
> To change your subscription options or unsubscribe:
More information about the Baypiggies