Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between None and <no value>

Tags:

python

numpy

I'm familiar with Java's null and C++'s nullptr, plus similar concepts from several scripting languages. None looks remarkably like Python's version of that same old theme.

And then I ran across this function declaration:

 numpy.amin(a, axis=None, out=None, keepdims=<no value>, initial=<no value>, where=<no value>)

What's the difference between None and <no value>? I'm guessing this is just a documentation generation thing when there's no defined default, but then why not just not list a default at all?

like image 364
Mark Storer Avatar asked Jun 18 '26 15:06

Mark Storer


1 Answers

It's just a documentation thing, there is no such concept in Python itself.

Take into account that None in itself is also a valid object. Sometimes you want to accept None as a valid value for an argument, so you can't use that as the default value for an optional parameter. You wouldn't be able to distinguish between the default None and someone passing in None explicitly, since it's a singleton!

If I needed to define such a function, I'd use a different singleton sentinel. You can create one from just about anything, but simplest is to use an object() instance:

_sentinel = object()

def foo(bar, baz=_sentinel):
    if baz is not _sentinel:
        # baz has a defined value, because it is
        # not a reference to the sentinel

And perhaps I'd also use <no value> in the documentation to indicate that baz is optional. It all depends on the local conventions. The Python documentation itself uses [...] around optional arguments, for example.

numpy.amin() is actually a proxy function; it delegates the actual work either to numpy.minimum() (via ufunc.reduce(), or, if the first argument is a subclass that implements an amin() method, to that method of the subclass. Because the latter should be able to set their own defaults, using a sentinel lets the numpy.amin() implementation pass on only those keyword arguments that actually were given an explicit value, without dictating what kind of sentinel the subclass .amin() implementations should use or what types they accept.

The Numpy project actually created their own singleton class to act as a sentinel so they could give the object a helpful repr() output:

>>> from numpy._globals import _NoValue
>>> _NoValue
<no value>
>>> type(_NoValue)
<class 'numpy._globals._NoValueType'>

Finally, None should not be compared with null or nullptr. None is a singleton object, something to reference instead of another object. null and nullptr are used to signal the absence of a reference, and can be passed around like other scalar values. You can't do this in Python, where everything is a valid reference to an object. (At most, you get a NameError or UnboundLocal exception if you tried to use a name that hasn't been bound to yet in its namespace).

like image 96
Martijn Pieters Avatar answered Jun 21 '26 04:06

Martijn Pieters