Search code examples
pythonccpython

Value of Py_None


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?


Solution

  • 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.