长亭百川云 - 文章详情

Python 的 None 是怎么实现的?

古明地觉的编程教室

45

2024-07-13

楔子

本篇文章来聊一聊 None 是怎么实现的,None 在 Python 里面也是一个对象,用于表示空(值不存在的情况)。比如基于主键从数据库获取记录,如果没有查询到,那么一般会返回 None。

另外如果函数没有返回值,那么会隐式地返回 None,表示返回的是空。

None 的底层结构

和其它对象不同,由于 None 没有额外的实体数据,所以它在底层就是一个 PyObject 结构体实例。因此也能看出,None 的大小为 16 字节。

// Objects/object.c  
PyObject _Py_NoneStruct = {  
    _PyObject_EXTRA_INIT  
    { _Py_IMMORTAL_REFCNT },  
    &_PyNone_Type  
};

None 在底层只包含引用计数和类型,引用计数为 2 ** 32 - 1,所以 None 是一个永恒对象,然后类型为 _PyNone_Type。由于变量都是 PyObject *,所以和布尔值一样,解释器也提供了相应的宏,从而方便使用。

// Include/object.h  
#define Py_None (&_Py_NoneStruct)

注意:None 是单例的,如果要判断对象是否为空,应该使用 is 关键字。

// Objects/object.c  
// Python 虽然一切皆对象,但你能拿到的都是对象的指针  
// 所以变量本质上就是指针,但操作变量时会自动操作变量指向的内存  
// 而 is 用于判断两个变量是否引用同一个对象  
// 那么底层只需要判断这两个变量保存的地址是否相同即可  
int Py_Is(PyObject *x, PyObject *y)  
{  
    // 所以 is 在底层就是一个 == 判断  
    return (x == y);  
}  
  
// x is None,只需判断 x 保存的地址和 Py_None 是否相同  
int Py_IsNone(PyObject *x)  
{  
    return Py_Is(x, Py_None);  
}  
  
// x is True,只需判断 x 保存的地址和 Py_True 是否相同  
int Py_IsTrue(PyObject *x)  
{  
    return Py_Is(x, Py_True);  
}  
  
// x is False,只需判断 x 保存的地址和 Py_False 是否相同  
int Py_IsFalse(PyObject *x)  
{  
    return Py_Is(x, Py_False);  
}

比较简单,相信对你来说已经没有任何难度了。

None 的类型

说完了 None 本身,再来看看它的类型。

print(type(None))  
"""  
<class 'NoneType'>  
"""

None 的类型是 NoneType,但这个类解释器没有暴露给我们,需要通过 type 去获取。

class MyNone(type(None)):  
    pass  
"""  
TypeError: type 'NoneType' is not an acceptable base type  
"""

注意:NoneType 无法被继承,当然我们一般也不会去继承它。

然后看一下 NoneType 的底层结构,它位于 Objects/object.c 中。

NoneType 的类型也是 type,然后它实现了 tp_as_number。

// Objects/object.c  
static PyNumberMethods none_as_number = {  
    // ...  
    (inquiry)none_bool,         /* nb_bool */  
    // ...  
};

但是只实现了里面的 nb_bool,用于生成布尔值。

// Objects/object.c  
static int  
none_bool(PyObject *v)  
{  
    return 0;  
}

函数返回的是 0,因此调用 PyBool_FromLong 的时候,会返回 Py_False。

print(bool(None))  # False  
print(not not None)  # False

小结

以上我们就简单介绍了 None,当然内容有些过于简单了,因为 None 本身就没多少内容,核心就两点:

  • None 是单例的;
相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2