3

I have two python objects a and b.

What is the best/most-efficient/most-pythonic way to check if exactly one of these objects is None?

Saqib Ali
  • 11,931
  • 41
  • 133
  • 272
  • 3
    You seem to be asking 3 different questions. Do you want the best, the most efficient, or the most Pythonic? The first and third are opinions, so off-topic. The 2nd is probably not important: [Premature optimization is the root of all evil](http://c2.com/cgi/wiki?PrematureOptimization) – Barmar May 25 '18 at 17:32
  • `if not` perhaps? – pstatix May 25 '18 at 17:32
  • 1
    `sum(x is None for x in (a,b)) == 1` that sounds overkill, though :) – Jean-François Fabre May 25 '18 at 17:34
  • 2
    `(a is None) != (b is None)` – Barmar May 25 '18 at 17:34
  • @Jean-FrançoisFabre that trades on the booleans in Python being numbers, and I know they are, but it still bugs me that we leverage it. It makes me feel dirty in a type-violation sort of way. – pcurry May 25 '18 at 17:37
  • 1
    booleans are integers. `True == 1`, `False == 0`. that's written in stone – Jean-François Fabre May 25 '18 at 17:38

2 Answers2

10

Use Python's ^ (XOR) operator.

(a is None) ^ (b is None)
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
  • 1
    I am torn as to whether or not it is preferable to use `!=`. Yes, logical and bitwise XOR are equivalent for booleans, but still... – juanpa.arrivillaga May 25 '18 at 17:35
  • @juanpa.arrivillaga I'm torn too. When I think "exactly one of two booleans is True" I automatically think XOR, but `!=` fits just as well. – Bill the Lizard May 25 '18 at 17:39
  • This is why I referenced the older question here: https://stackoverflow.com/questions/432842/how-do-you-get-the-logical-xor-of-two-variables-in-python – pcurry May 25 '18 at 17:40
  • Yes, for me the problem is the distinction between bitwise and logical operators. Unfortunately, python doesn't have a logical exclusive-or operator. When I glance at the code and see the bitwise `^`, I think "there's some bitwise operation going on here", but on the other hand, `!=` isn't immediatebly "XOR" in my head. – juanpa.arrivillaga May 25 '18 at 17:41
  • I did a quick benchmark and ^ seems to be marginally more efficient. – Olivier Melançon May 25 '18 at 17:44
5

What you effectively want is the XOR or Exclusive OR function on whether those two objects are None. The following should work for you:

(a is None) ^ (b is None)

A more exhaustive answer on how to get XOR on objects in Python can be found here:

How do you get the logical xor of two variables in Python?

pcurry
  • 1,374
  • 11
  • 23