楔子
None 在 Python 里面也是一个对象,用于表示空(值不存在的情况)。比如基于主键从数据库获取记录,如果没有查询到,那么一般会返回 None。另外如果函数没有返回值,那么也会隐式地返回 None,表示返回的是空。
本篇文章就来聊一聊 None 是怎么实现的。
None 的底层结构
和其它对象不同,由于 None 没有额外的实体数据,所以它在底层就是一个 PyObject 结构体实例。因此也能看出,None 的大小为 16 字节。
// Objects/object.c
PyObject _Py_NoneStruct = {
_PyObject_EXTRA_INIT
1, &_PyNone_Type
};
None 在底层只包含引用计数和类型,然后类型为 _PyNone_Type。由于变量都是 PyObject *,所以和布尔值一样,解释器也提供了相应的宏,从而方便使用。
// Include/object.h
#define Py_None (&_Py_NoneStruct)
注意:None 是单例的,如果要判断对象是否为空,应该使用 is 关键字。
None 的类型
说完了 None 本身,再来看看它的类型。
print(type(None)) # <class 'NoneType'>
None 的类型是 <class 'NoneType'>,但这个类解释器没有暴露给我们,需要通过 type 去获取。注意:NoneType 无法被继承,当然我们一般也不会去继承它。
class MyType(type(None)):
pass
"""
TypeError: type 'NoneType' is not an acceptable base type
"""
然后看一下 NoneType 的底层结构,它位于 Objects/object.c 中。
PyTypeObject _PyNone_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"NoneType",
0,
0,
none_dealloc, /*tp_dealloc*/ /*never called*/
0, /*tp_vectorcall_offset*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_as_async*/
none_repr, /*tp_repr*/
&none_as_number, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call */
0, /*tp_str */
0, /*tp_getattro */
0, /*tp_setattro */
0, /*tp_as_buffer */
Py_TPFLAGS_DEFAULT, /*tp_flags */
0, /*tp_doc */
0, /*tp_traverse */
0, /*tp_clear */
0, /*tp_richcompare */
0, /*tp_weaklistoffset */
0, /*tp_iter */
0, /*tp_iternext */
0, /*tp_methods */
0, /*tp_members */
0, /*tp_getset */
0, /*tp_base */
0, /*tp_dict */
0, /*tp_descr_get */
0, /*tp_descr_set */
0, /*tp_dictoffset */
0, /*tp_init */
0, /*tp_alloc */
none_new, /*tp_new */
};
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 是单例的;
- 判断的时候使用 is 关键字;
欢迎大家关注我的公众号:古明地觉的编程教室。
如果觉得文章对你有所帮助,也可以请作者吃个馒头,Thanks♪(・ω・)ノ。