
Steve Dower writes:
But for me, the ?? operator makes its strongest case when you are getting attributes from potentially None values:
x = maybe_get()?.get_int() ?? 0 y = maybe_get()?.get_list() ?? []
In this case, using 'or' may replace an intentionally falsie value with your own,
I wish the PEP's examples had such cases marked and explained. I didn't understand the context for most examples (ie, *why* the left operand could be None, and why that needed to be distinguished from "intentionally falsie values"). In the "find_content_type" example, None is just a way of saying "oops, you handle it" that is less "cute" than "". "or" is far more resilient in that context than "??" would be. I am a mail geek, and *much* more likely to encounter that code than the others. I would be distressed if the email module or Mailman grew a lot of "??". Email is a domain where resilience really matters because you can receive arbitrary data over SMTP, there's no provision for rejecting garbage, and all too often you do get garbage. :-/
while using a default parameter is still going to leave you with None if the first maybe_get() returned nothing.
"?." without "??" feels like a trap, while "??" without "?." feels largely unnecessary. But both together lets you turn many lines of code into a much shorter snippet that reads left-to-right and lets you assume success until you reach the "??".
I find that pretty persuasive. Perhaps that should be added to PEP 8. I would advocate write those x = maybe_get() ?. get_int() ?? 0 y = maybe_get() ?. get_list() ?? [] to emphasize that this is an operator that "does something" to the operand, rather than "just" extracting an attribute. (No, I'm not going to try to make that more precise, so feel free to ignore.) I'm not sure about the ?[ operator: x = a?[b] ?? c x = a ?[b] ?? c x = a ?[ b] ?? c x = a ?[ b ] ?? c I guess I like the second line best (and x = a?[b]??c is right out, of course). I do think Terry Reedy's criticism that in many cases having maybe_get() return None rather than an appropriate default object is bad API design may be important. I suspect that the "a ?. b ?? c" pattern will discourage refactoring of that code in favor of writing short workarounds.