[Python-ideas] Fwd: Null coalescing operator

David Mertz mertz at gnosis.cx
Sat Sep 10 22:49:30 EDT 2016


For kicks I looked at the code in a commercial product that we are open
sourcing very soon at Continuum Analytics.  It has about 27k lines of
Python and Cython.  I checked it just by running `grep -C3 'if.*None'` over
the source code and eyeballing.

Obviously, this code might be refactored if other syntax was available.
And I personally wrote only a small part of the code, so I might write it
differently either way.  But looking through, the uses of 'is (not) None' I
found fell into a few categories.

Some were suites of statements under the 'foo is None' branch.  Those would
have to remain suites.  Some are single line returns, other single line
raise.  Those I call 'value' are the ones that would lend themselves to the
'bar = foo ?? baz' style.  The ones I call 'attribute' are the cases where
we test for non-None before accessing an attribute of the object.

The thing that I found surprisingly common was cases where a compound
condition was used, e.g. 'if x is None and y > 37'.  Those might be
possible to refactor, but cannot be directly rewritten in the coalescing
style.

  - Suite: 75
  - Return: 21
  - Raise: 13
  - Value: 46
  - Attribute: 2
  - Compound condition: 25

On Sat, Sep 10, 2016 at 7:15 PM, David Mertz <mertz at gnosis.cx> wrote:

> How much of the time is a branch of the None check a single fallback value
> or attribute access versus how often a suite of statements within the
> not-None branch?
>
> I definitely check for None very often also. I'm curious what the
> breakdown is in code I work with.
>
> On Sep 10, 2016 7:10 PM, "Guido van Rossum" <guido at python.org> wrote:
>
>> To the contrary. I read and write code that performs explicit checks
>> for None all the time. Catching AttributeError is often a code smell
>> or at least a measure of last resort.
>>
>> On Sat, Sep 10, 2016 at 6:46 PM, David Mertz <mertz at gnosis.cx> wrote:
>> > Ok, I have been thinking of the behavior too broadly. I realize now that
>> > `x?.foo` might still simply raise an AttributeError if x is neither
>> None nor
>> > a thing with a foo attribute.
>> >
>> > The class I wrote is definitely too aggressive for the behavior
>> described.
>> > On the other hand, by being narrower in behavior there feels like even
>> less
>> > motivation for new syntax.
>> >
>> >
>> > On Sep 10, 2016 6:29 PM, "MRAB" <python at mrabarnett.plus.com> wrote:
>> >>
>> >> On 2016-09-11 02:02, David Mertz wrote:
>> >>>
>> >>> On Sat, Sep 10, 2016 at 5:23 PM, Guido van Rossum <guido at python.org
>> >>> <mailto:guido at python.org>> wrote:
>> >>>
>> >>>     No. PEP 505 actually solves the problem without ever catching
>> >>>     AttributeError. Please read it.
>> >>>
>> >>>
>> >>> I read it again (I did a year ago, but reviewed it now).  I hadn't
>> been
>> >>> thinking that the *mechanism* of a new None-coalescing operator would
>> >>> actually be catching an exception.  It could (and should) work
>> >>> differently if it becomes syntax.
>> >>>
>> >>> What I was getting at with "essentially" was that it would *do the
>> same
>> >>> thing* that an AttributeError does.  That is, if `x.foo` can't be
>> >>> evaluated (i.e. x doesn't have an attribute 'foo'), then access is
>> >>> informally "an error."  The hypothetical "x?.foo" catches that "error"
>> >>> and substitutes a different value.  The particular implementation
>> >>> under-the-hood is less important for most programmers who might use
>> the
>> >>> construct (and I think documentation would actually give an informal
>> >>> equivalent as something similar to what I put in the NoneCoalesce
>> class).
>> >>>
>> >> x?.foo would lookup attribute 'foo' _unless_ x was None, in which case
>> it
>> >> would return None. It's simply:
>> >>
>> >>     None if x is None else x.foo
>> >>
>> >> This means that None?.__str__() would return None, not 'None'. (None
>> has
>> >> an attribute called '__str__', and None.__str__() returns 'None', but
>> it
>> >> would not be looked up because None is, well, None.)
>> >>
>> >> _______________________________________________
>> >> Python-ideas mailing list
>> >> Python-ideas at python.org
>> >> https://mail.python.org/mailman/listinfo/python-ideas
>> >> Code of Conduct: http://python.org/psf/codeofconduct/
>> >
>> >
>> > _______________________________________________
>> > Python-ideas mailing list
>> > Python-ideas at python.org
>> > https://mail.python.org/mailman/listinfo/python-ideas
>> > Code of Conduct: http://python.org/psf/codeofconduct/
>>
>>
>>
>> --
>> --Guido van Rossum (python.org/~guido)
>>
>


-- 
Keeping medicines from the bloodstreams of the sick; food
from the bellies of the hungry; books from the hands of the
uneducated; technology from the underdeveloped; and putting
advocates of freedom in prisons.  Intellectual property is
to the 21st century what the slave trade was to the 16th.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20160910/fa8b6d26/attachment.html>


More information about the Python-ideas mailing list