[Python-ideas] Null coalescing operators

Brendan Barnwell brenbarn at brenbarn.net
Tue Sep 22 05:40:59 CEST 2015


On 2015-09-21 15:56, Carl Meyer wrote:
> My jaw dropped a bit when I saw it asserted in this thread that
> functions returning "useful value or None" is an anti-pattern. I write
> functions like that all the time, and I consider it a useful and
> necessary Python idiom. I would hate to rewrite all that code to either
> deal with exceptions or add default-value-argument boilerplate to all of
> them; when "no result" is an expected and normal possibility from a
> function, letting the calling code deal with None however it chooses is
> much nicer than either of those options.

	I agree that it's a fine thing.  The thing is, it's an API choice.  If 
your API is "return such-and-such or None", then anyone who calls your 
function knows they have to check for None and do the right thing.  I 
think this is fine if None really does indicate something like "no 
result".  (The re module uses None return values this way.)

	It seems to me that a lot of the "problem" that these null-coalescing 
proposals are trying to solve is dealing with APIs that return None when 
they really ought to be raising an exception or returning some kind of 
context-appropriate empty value.  If you're doing result = 
someFunction() and then result.attr.upper() and it's failing because 
result.attr is None, to me that's often a sign that the API is fragile, 
and the result object that someFunction returns should have its attr set 
to an empty string, not None.

	In other words, if you really want "a null result that I can call all 
kinds of string methods on and treat it like a string", you should be 
returning an empty string.  If you want "a null result I can subscript 
and get an integer", you should be returning some kind of 
defaultdict-like object that has a default zero value.  Or whatever. 
There isn't really such a thing as "an object to which I want to be able 
to do absolutely anything and have it work", because there's no 
type-general notion of what "work" means.  From a duck-typing 
perspective, if you expect users to try to do anything with a value you 
return, what they might reasonably want to do should be a clue as to 
what kind of value you should return.

	That still leaves the use-case where you're trying to interoperate with 
some external system that may have missing values, but I don't see that 
as super compelling.  Getting an exception when you do 
some['big']['json']['object']['value'] and one of the intermediate ones 
isn't there is a feature; the bug is the JavaScripty mentality of just 
silently passing around "undefined".  To my mind, Python APIs that wrap 
such external data sources should ideally take the opportunity to 
improve on them and make them more Pythonic, by providing sensible, 
context-relevant defaults instead of propagating a generic "null" value 
willy-nilly.

-- 
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