4 ms·
I sometimes use your "bug" on purpose in tests, when checking that two values are either both defined or both undefined, but not one defined and one undefined:
by sleavey 6y ago
I sometimes use your "bug" on purpose in tests, when checking that two values are either both defined or both undefined, but not one defined and one undefined:
$ python
>>> a, b = 1, 2
>>> bool(a) ^ bool(b)
False
>>> a, b = 1, 1
>>> bool(a) ^ bool(b)
False
>>> a, b = None, None
>>> bool(a) ^ bool(b)
False
>>> a, b = None, 1
>>> bool(a) ^ bool(b)
True
(Note: this doesn't work if a value can be 0, because bool(0) is False in Python).
This helps to avoid having to write something like `(a is not None and b is not None) or (a is None and b is None)`.
- shiftingleft 6y agoYour note is very important, I think it would be good to give it more emphasis. What works flawlessly, however, is: In [1]: a = None In [2]: b = 0 In [3]: (a is None) ^ (b is None) Out[3]: True Alternatively, as suggested in another comment, you can use inequality as a replacement for XOR: In [4]: (a is None) != (b is None) Out[4]: True Another error prone pattern is the following: In [5]: a or b Out[5]: 0 Which can behave differently depending on the order of elements/values: In [6]: b or a Out[6]: None # should be 0 Since b is zero, it doesn't count. Less error prone, but also more verbose is: In [10]: a if a is not None else b Out[10]: 0
- sleavey 6y agoLesson for myself: check my working. The test I actually used the XOR in, that I was referring to, uses the first example you wrote - I agree, this is much better. However, I also like your second example, which is arguably clearer. Thanks!
- gfodor 6y agoNot a python person, but I usually do this in other languages via an equality check `(a != nil) == (b != nil)` etc
- patrec 6y agoYou are aware that ^ on a 1 bit value (like a boolean) is just !=, right?
- sleavey 6y agoHah, I wrote that code on the fly and didn't check the aforementioned test implementation, where I had `(a is None) ^ (b is None)` like the other commenter suggested.
- patrec 6y agoYou could just write this as (a is None) is not (b is None) or (a is None) != (b is None) It won't make a difference (and is 1 to to 5 characters longer), but it seems "cleaner" since it's more specific.