[Python-ideas] PEP 531: Existence checking operators
Steven D'Aprano
steve at pearwood.info
Sat Oct 29 06:53:23 EDT 2016
On Sat, Oct 29, 2016 at 02:52:42PM +1000, Nick Coghlan wrote:
> On 29 October 2016 at 04:08, Mark Dickinson <dickinsm at gmail.com> wrote:
> > On Fri, Oct 28, 2016 at 9:30 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> >> [...] the current practicises of:
> >>
> >> * obj is not None (many different use cases)
> >> * obj is not Ellipsis (in multi-dimensional slicing)
> >
> > Can you elaborate on this one? I don't think I've ever seen an `is not
> > Ellipsis` check in real code.
>
> It's more often checked the other way around: "if Ellipsis is passed
> in, then work out the multi-dimensional slice from the underlying
> object"
>
> And that reflects the problem Paul and David highlighted: in any
> *specific* context, there's typically either only one sentinel we want
> to either propagate or else replace with a calculated value, or else
> we want to handle different sentinel values differently, which makes
> the entire concept of a unifying duck-typing protocol pragmatically
> dubious, and hence calls into question the idea of introducing new
> syntax for working with it.
>
> On the other hand, if you try to do this as an "only None is special"
> kind of syntax, then any of the *other* missing data sentinels (of
> which we have 4 in the builtins alone, and 5 when you add the decimal
> module) end up being on much the same level as "arbitrary sentinel
> objects" in the draft PEP 531, which I would consider to be an
> incredibly poor outcome for a change as invasive as adding new syntax:
> https://www.python.org/dev/peps/pep-0531/#arbitrary-sentinel-objects
Hmmm. I see your point, but honestly, None *is* special. Even for
special objects, None is even more special. Here are your examples
again:
* obj is not None (many different use cases)
* obj is not Ellipsis (in multi-dimensional slicing)
* obj is not NotImplemented (in operand coercion)
* math.isnan(value)
* cmath.isnan(value)
* decimal.getcontext().is_nan(value)
Aside from the first, the rest are quite unusual:
- Testing for Ellipsis occurs in __getitem__, and not even
always then.
- Testing for NotImplemented occurs in operator dunders,
rarely if ever outside those methods. (You probably
should never see NotImplemented except in an operator
dunder.)
In both cases, this will be a useful feature for the writer of the
class, not the user of the class.
- Testing for NAN is really only something of interest to
those writing heavily numeric code and not even always
then.
You can go a LONG way with numeric code by just assuming that x is a
regular number, and leaving NANs for "version 2". Especially in Python,
which typically raises an exception where it could return a NAN. In
other words, its quite hard to generate an unexpected NAN in Python.
So these examples are all quite special and of very limited
applicability and quite marginal utility. My guess is that the majority
of programmers will never care about these cases, and of those who do,
they'll only need it quite rarely. (We use classes far more often than
we write classes.)
But None is different. My guess is that every Python programmer, from
the newest novice to the most experienced guru, will need to check for
None, and likely frequently.
So my sense is that of all the use-cases for existence checking divide
into two categories:
- checking for None (> 95%)
- everything else (< 5%)
I did a very rough search of the Python code on my system and found
this:
is [not] None: 10955
is [not] Ellipsis: 13
is [not] NotImplemented: 285
is_nan( / isnan( : 470
which is not far from my guess.
--
Steve
More information about the Python-ideas
mailing list