[Python-ideas] Discussion about a 'xor' keyword?

Andrew Barnert abarnert at yahoo.com
Sun Oct 18 07:18:21 CEST 2015


First, it seems like if this operator were to exist, it should be defined in terms of "and", "or", and "not" in one of the usual ways: "a and not b or b and not a", or "(a or b) and not (a and b)".

Of course this means it returns False, not None, if both values are falsey or both truthy, but I think that's what you'd want anyway. While you sometimes do want the value of "a and b" or "a or b", it's far more common to just want the truthiness of that value (as in "if a or b:"), and, while None is falsey, it's not the canonical falsey value.

But anyway, as my replies below explain, I don't think it should exist.

On Saturday, October 17, 2015 6:54 PM, Emanuel Barry <vgr255 at live.ca> wrote:

>I have a few from the top of my head (not backed by code right now, will post some when I feel like digging into it).


But all of these ideas are just as well served by a function as by a new keyword.

There are two reasons for "and" and "or" to be operators.

First, functions can't short-circuit. That's obviously not relevant to "xor", because by definition, it has to evaluate both operands.

Second, function calls chained in a complicated expression can look ugly compared to operators—compare "or(and(a, b), and(c, d))" to "a and b or c and d". But that isn't relevant to "xor" either. I think most readers would find "a xor b xor c xor d xor e" confusing and have to work through its meaning—and, in fact, they'd find xor(a, xor(b, xor(c, xor(d, e))))" (or the reverse associativity) easier to understand. Worse, I think some readers would _think_ they understand what it means and be wrong (exactly one, or some but not all, or exactly half). And, more importantly, I don't think they'd ever want what it does. It's pretty common to want to check that one or all of three values are true, but when would you ever want to check that an odd number of those three values are true? (You might occasionally want to check that an odd number of the possibly-only-known-at-runtime members of some iterable are true, but for that, you'd use a function akin to "any" and "all", maybe called "parity".)

>'xor' would by no means be as common as any existing operator, but I believe it is a good addition to consider. Another upside is that keywords only evaluate the value once, so chaining two wouldn't re-evaluate the value (in the case of a function/property).


Again, I don't think you'd want to chain them. But, even if you did, functions also only evaluate their arguments once, so there's no advantage here anyway.

For example, try this:


    def xor(a, b):
        return a and not b or b and not a

    xor((print('spam'), 2)[1], (print('eggs'), 3)[1])

Of course "spam" and "eggs" only get printed once, because what gets passed to "xor" isn't the expression "(print('spam'), 2)[1]", it's the value of that expression, "2".

And likewise, xor(a, xor(b, c)) isn't going to cause b or c to get evaluated twice. And of course neither would "parity((a, b, c))" or "some((a, b, c))", etc.

And I'm not sure what you mean by "property" here.

>From that 2009 discussion, most of the rejections focused on "You can coerce to bool before then perform the xor operations", but I'm considering not coercing to bool here, so I think it is different enough to the other discussion to (at least in my opinion) bring it up one more time. If I wanted boolean coercion, I'd just do it myself.


But you can also just do it yourself _without_ boolean coercion, so how is this any different?


More information about the Python-ideas mailing list