[Python-ideas] PEP 505: None-aware operators

Brendan Barnwell brenbarn at brenbarn.net
Thu Jul 19 14:36:14 EDT 2018


On 2018-07-19 02:11, Chris Angelico wrote:
> Okay. What about bitwise operators, then? They don't have centuries of
> mathematical backing to support them, yet it isn't considered
> "unpythonic" to have &|^~ peppering our code. Judging by the current
> levels of backlash against symbolic operators, it would have been
> better to use "more explicit" function calls for all bitwise
> operations. Coalescing None to a value is_at least_  as common as
> performing bit manipulations in integers.

	The use of & to mean "and" does indeed have centuries of backing to 
support it.  The other operators, and the use of & to specifically mean 
bitwise-and, are newer, but still go back decades in other programming 
languages.  Moreover, the fact that these are bitwise versions of more 
general logical operations (conjunction, disjunction, etc.) means that 
they can be overridden for custom types in a way that is still 
intuitive.  For instance, sets override & to mean "intersection" because 
it means "everything that is in set A AND in set B", and similarly for | 
and ^.

	So basically I do not regard these operators as bitwise operators. 
They are symbols standing for logical operations.  Their default 
implementations on built-in numeric types do bitwise operations, but 
that is not what the symbols "mean".  Their meaning is more general and 
bitwise operations are one reasonable narrowing of that meaning for use 
in the context of builtin numeric types, but there are many other uses 
of these symbols that are equally consistent with their meaning.

	To me, this notion of symbols with an abstract meaning which can be 
narrowed for particular types by overriding magic methods is one of 
Python's greatest strengths.  + doesn't mean "add two numbers", it means 
"add", and that makes sense for many types, and they can override 
__add__ to define sensible behavior for their own purposes.  [] doesn't 
mean "get list item" it means "get", and types can override __getitem__ 
to define sensible behavior for their own purposes.

	As far as I can see, these null-coalescing operators would break that 
model.  The PEP doesn't seem to provide for a "real" magic method 
allowing users to override the actual behavior of the method.  (You can 
only override __has_value__ to hook into it, but not define by fiat what 
A ?? B does, as you can with other operators.)  And I think the reason 
for this is that the operator itself is too specific, much more specific 
in semantics than other operators.  (I had similar doubts about adding 
the matrix-multiplication operator @.)

	People keep saying that this null-coalescing behavior is so common and 
useful, etc., but that hasn't been my experience at all.  In my 
experience, the desire to shortcut this kind of logic is more often a 
sign of corner-cutting and insufficiently specified data formats, and is 
likely to cause bugs later on.  Eventually it has to actually matter 
whether something is None or not, and these operators just kick that can 
down the road.  In terms of their abstract meaning, they are not 
remotely close to as common or useful as operators like & and |.

-- 
Brendan Barnwell
"Do not follow where the path may lead.  Go, instead, where there is no 
path, and leave a trail."
    --author unknown


More information about the Python-ideas mailing list