On Sat, Oct 29, 2016 at 02:52:42PM +1000, Nick Coghlan wrote:
> On 29 October 2016 at 04:08, Mark Dickinson <dicki...@gmail.com> wrote:
> > On Fri, Oct 28, 2016 at 9:30 AM, Nick Coghlan <ncogh...@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
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to