It is clear to me that None
is used to signify the lack of a value. But since everything must have an underlying value during implementation, I'm looking to see what value has been used in order to signify the absence of a value, regarding CPython
.
I understand, based on the documentation, that NoneObject
is a singleton. Since my c
skills are rusty, my best, amateur guess, would be that the value of None
would be the pointer to the memory allocated for the Py_None
object; since it is a singleton this would guarantee uniqueness. Or is it assigned to c
's NULL
which has a value of 0x0000
based on the second answer in this question?
Additionally, the documentation also points out:
Note that the PyTypeObject for None is not directly exposed in the Python/C API.
Which I'm guessing means you cannot find it searching through source. (Which I did, not knowing where to look, for object.c
naively believing I could understand anything)
But I'm not certain about my opinion on this so I asked.
What is the c
level value for the Py_None
object in CPython
?
Py_None
is a macro definition in Include/object.h
. It is a an alias for _Py_NoneStruct
in object.c
which is a static (as in storage) global variable of PyObject
type (which is a struct). It is assigned in Python terms to be of NoneType
(defined right above it in object.c
and only used once for _Py_NoneStruct
).
So it's not NULL or any other special value in C, it's a singleton PyObject
instance of _PyNone_Type
. As for the _PyNone_Type
PyTypeObject
not being exposed, I suppose they refer to the static
keyword (i.e. internal linkage) which means that the PyTypeObject
is only accessible within object.c
and is only used once for the definition of PyNone
.
Just to add to this a bit, whenever the documentation says that PyNone
has no type, it should not be taken literally. It has a special kind of type, NoneType
, which you can still access through the None
singleton but you can't create new instances or do any other thing you can do with a normal type. There seems to be a hard-coded limitation for not creating new instances, and although I can't find exactly where it's defined in the CPython source you can see its effect when trying to create a new instance:
>>> type(None)
<type 'NoneType'>
>>> type(None)()
Traceback (most recent call last):File "<stdin>", line 1, in <module>
TypeError: cannot create 'NoneType' instances
EDIT: It seems that the error is thrown from typeobject.c
when the tp_new
field is NULL. Surprisingly though _PyNone_Type
seems to be defined with a non-NULL tp_new
(points to the static none_new
in object.c
). It might be set to NULL afterwards at some point, but it's just an implementation detail and doesn't really make a difference for the scope of your question.