对于 Python 来说,一切都是对象 。 这句话很重要,当你对某个特性不了解时,回想下这句话也许就能想通

一个整数一个对象,一个浮点数也是一个对象,一个函数也是一个对象

>>> isinstance(3,object)

True

>>> isinstance(3.14, object)

True

>>> isinstance(max,object)

True

既然一切都是对象,那么这一切应该都有一个类来创建。它们都有一个公共的基础类,这个基础类就是 object

一切都是对象

object

如果我们使用 type() 函数来检查下它们的类型,就会发现

>>> type(1)

>>> type(1)

>>> type(3.14)

>>> type(max)

那么 int 、float 和 builtin_function_or_method 又是什么呢?

>>> type(int)

>>> type(int)

>>> type(float)

>>> type(builtin_function_or_method)

Traceback (most recent call last):

File "", line 1, in

NameError: name 'builtin_function_or_method' is not defined

但,其实,object 也是一个对象

>>> type(object)

type()

看到这里,想必对 type 这个类型很好奇,到底是什么鬼?

一探究竟的事情,我们等下再说,我们先来了解下 type() 函数的原理

type() 函数是一个内建可调用类,只有一个参数的情况下,它的作用相当于访问参数的 __class__ 属性

>>> type(int)

>>> int.__class__

更有意思的是,type(type) 的结果还算是

>>> type(type)

>>> type.__class__

什么意思,也就是自己创建了自己? 这....

越挖越深,算了,以后有篇幅再来讲解 type()

我们先挖一下源码,因为 type() 、int 、float 都说是内建函数,所以我们找到内建函数的源码

在 Python 目录下的 bltinmodule.c 文件中的第 2892 行开始

SETBUILTIN("None", Py_None);

SETBUILTIN("Ellipsis", Py_Ellipsis);

SETBUILTIN("NotImplemented", Py_NotImplemented);

SETBUILTIN("False", Py_False);

SETBUILTIN("True", Py_True);

SETBUILTIN("bool", &PyBool_Type);

SETBUILTIN("memoryview", &PyMemoryView_Type);

SETBUILTIN("bytearray", &PyByteArray_Type);

SETBUILTIN("bytes", &PyBytes_Type);

SETBUILTIN("classmethod", &PyClassMethod_Type);

SETBUILTIN("complex", &PyComplex_Type);

SETBUILTIN("dict", &PyDict_Type);

SETBUILTIN("enumerate", &PyEnum_Type);

SETBUILTIN("filter", &PyFilter_Type);

SETBUILTIN("float", &PyFloat_Type);

SETBUILTIN("frozenset", &PyFrozenSet_Type);

SETBUILTIN("property", &PyProperty_Type);

SETBUILTIN("int", &PyLong_Type);

SETBUILTIN("list", &PyList_Type);

SETBUILTIN("map", &PyMap_Type);

SETBUILTIN("object", &PyBaseObject_Type);

SETBUILTIN("range", &PyRange_Type);

SETBUILTIN("reversed", &PyReversed_Type);

SETBUILTIN("set", &PySet_Type);

SETBUILTIN("slice", &PySlice_Type);

SETBUILTIN("staticmethod", &PyStaticMethod_Type);

SETBUILTIN("str", &PyUnicode_Type);

SETBUILTIN("super", &PySuper_Type);

SETBUILTIN("tuple", &PyTuple_Type);

SETBUILTIN("type", &PyType_Type);

SETBUILTIN("zip", &PyZip_Type);

可以看到

int 是一个对 PyLong_Type 的引用

float 是一个对 PyFloat_Type 的引用

object 是一个对 PyBaseObject_Type 的引用

type 是一个对 PyType_Type 的引用

继续追查,我们可以看到如下定义

Include/longobject.h

PyAPI_DATA(PyTypeObject) PyLong_Type;

Include/floatobject.h

PyAPI_DATA(PyTypeObject) PyFloat_Type;

Include/object.h

PyAPI_DATA(PyTypeObject) PyType_Type; /* built-in 'type' */

PyAPI_DATA(PyTypeObject) PyBaseObject_Type; /* built-in 'object' */

PyAPI_DATA(PyTypeObject) PySuper_Type; /* built-in 'super' */

所以,接下来我们就想知道 PyAPI_DATA 是什么鬼,这个在 pyport.h 中定义

#ifndef PyAPI_DATA

# define PyAPI_DATA(RTYPE) extern RTYPE

#endif

也就是说,经过预处理之后,它们就是下面这样

PyTypeObject PyLong_Type;

PyTypeObject PyFloat_Type

PyTypeObject PyType_Type;

PyTypeObject PyBaseObject_Type;

PyTypeObject PySuper_Type;

是什么意思呢? 它们都是 PyTypeObject 结构体的一个变量,所以它们的终极类型,结果都是 type

因为它们都是函数,这些函数都会传入一个字面量,然后返回一个对应类型的实例

所以,我们就要知道 PyTypeObject 到底是什么

#ifdef Py_LIMITED_API

typedef struct _typeobject PyTypeObject; /* opaque */

#else

typedef struct _typeobject {

PyObject_VAR_HEAD

const char *tp_name; /* For printing, in format "." */

Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation */

/* Methods to implement standard operations */

destructor tp_dealloc;

printfunc tp_print;

getattrfunc tp_getattr;

setattrfunc tp_setattr;

PyAsyncMethods *tp_as_async; /* formerly known as tp_compare (Python 2)

or tp_reserved (Python 3) */

reprfunc tp_repr;

/* Method suites for standard classes */

PyNumberMethods *tp_as_number;

PySequenceMethods *tp_as_sequence;

PyMappingMethods *tp_as_mapping;

/* More standard operations (here for binary compatibility) */

hashfunc tp_hash;

ternaryfunc tp_call;

reprfunc tp_str;

getattrofunc tp_getattro;

setattrofunc tp_setattro;

/* Functions to access object as input/output buffer */

PyBufferProcs *tp_as_buffer;

/* Flags to define presence of optional/expanded features */

unsigned long tp_flags;

const char *tp_doc; /* Documentation string */

/* Assigned meaning in release 2.0 */

/* call function for all accessible objects */

traverseproc tp_traverse;

/* delete references to contained objects */

inquiry tp_clear;

/* Assigned meaning in release 2.1 */

/* rich comparisons */

richcmpfunc tp_richcompare;

/* weak reference enabler */

Py_ssize_t tp_weaklistoffset;

/* Iterators */

getiterfunc tp_iter;

iternextfunc tp_iternext;

/* Attribute descriptor and subclassing stuff */

struct PyMethodDef *tp_methods;

struct PyMemberDef *tp_members;

struct PyGetSetDef *tp_getset;

struct _typeobject *tp_base;

PyObject *tp_dict;

descrgetfunc tp_descr_get;

descrsetfunc tp_descr_set;

Py_ssize_t tp_dictoffset;

initproc tp_init;

allocfunc tp_alloc;

newfunc tp_new;

freefunc tp_free; /* Low-level free-memory routine */

inquiry tp_is_gc; /* For PyObject_IS_GC */

PyObject *tp_bases;

PyObject *tp_mro; /* method resolution order */

PyObject *tp_cache;

PyObject *tp_subclasses;

PyObject *tp_weaklist;

destructor tp_del;

/* Type attribute cache version tag. Added in version 2.6 */

unsigned int tp_version_tag;

destructor tp_finalize;

#ifdef COUNT_ALLOCS

/* these must be last and never explicitly initialized */

Py_ssize_t tp_allocs;

Py_ssize_t tp_frees;

Py_ssize_t tp_maxalloc;

struct _typeobject *tp_prev;

struct _typeobject *tp_next;

#endif

} PyTypeObject;

#endif

结构体成员很多,我们只要记住第二个结构体成员 tp_name 就好,它表示当前的对象的类型

比如 PyLongType 在初始化的时候是这样的

Objects/longobject.c

PyTypeObject PyLong_Type = {

PyVarObject_HEAD_INIT(&PyType_Type, 0)

"int", /* tp_name */

offsetof(PyLongObject, ob_digit), /* tp_basicsize */

sizeof(digit), /* tp_itemsize */

long_dealloc, /* tp_dealloc */

0, /* tp_print */

0, /* tp_getattr */

0, /* tp_setattr */

0, /* tp_reserved */

long_to_decimal_string, /* tp_repr */

&long_as_number, /* tp_as_number */

0, /* tp_as_sequence */

0, /* tp_as_mapping */

(hashfunc)long_hash, /* tp_hash */

0, /* tp_call */

long_to_decimal_string, /* tp_str */

PyObject_GenericGetAttr, /* tp_getattro */

0, /* tp_setattro */

0, /* tp_as_buffer */

Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |

Py_TPFLAGS_LONG_SUBCLASS, /* tp_flags */

long_doc, /* tp_doc */

0, /* tp_traverse */

0, /* tp_clear */

long_richcompare, /* tp_richcompare */

0, /* tp_weaklistoffset */

0, /* tp_iter */

0, /* tp_iternext */

long_methods, /* tp_methods */

0, /* tp_members */

long_getset, /* 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 */

long_new, /* tp_new */

PyObject_Del, /* tp_free */

};

可以看到第二个参数 tp_name 就被设置为 "int"

同样的,我们可以看到 PyBaseObject_Type 变量的初始化为

typeobject.c

PyTypeObject PyBaseObject_Type = {

PyVarObject_HEAD_INIT(&PyType_Type, 0)

"object", /* tp_name */

sizeof(PyObject), /* tp_basicsize */

0, /* tp_itemsize */

object_dealloc, /* tp_dealloc */

0, /* tp_print */

0, /* tp_getattr */

0, /* tp_setattr */

0, /* tp_reserved */

object_repr, /* tp_repr */

0, /* tp_as_number */

0, /* tp_as_sequence */

0, /* tp_as_mapping */

(hashfunc)_Py_HashPointer, /* tp_hash */

0, /* tp_call */

object_str, /* tp_str */

PyObject_GenericGetAttr, /* tp_getattro */

PyObject_GenericSetAttr, /* tp_setattro */

0, /* tp_as_buffer */

Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */

PyDoc_STR("object()\n--\n\nThe most base type"), /* tp_doc */

0, /* tp_traverse */

0, /* tp_clear */

object_richcompare, /* tp_richcompare */

0, /* tp_weaklistoffset */

0, /* tp_iter */

0, /* tp_iternext */

object_methods, /* tp_methods */

0, /* tp_members */

object_getsets, /* tp_getset */

0, /* tp_base */

0, /* tp_dict */

0, /* tp_descr_get */

0, /* tp_descr_set */

0, /* tp_dictoffset */

object_init, /* tp_init */

PyType_GenericAlloc, /* tp_alloc */

object_new, /* tp_new */

PyObject_Del, /* tp_free */

};

tp_name 成员变量被设置为 object

同时在 typeobject.c 中还可以看到 PyType_Type 变量的初始化

PyTypeObject PyType_Type = {

PyVarObject_HEAD_INIT(&PyType_Type, 0)

"type", /* tp_name */

sizeof(PyHeapTypeObject), /* tp_basicsize */

sizeof(PyMemberDef), /* tp_itemsize */

(destructor)type_dealloc, /* tp_dealloc */

0, /* tp_print */

0, /* tp_getattr */

0, /* tp_setattr */

0, /* tp_reserved */

(reprfunc)type_repr, /* tp_repr */

0, /* tp_as_number */

0, /* tp_as_sequence */

0, /* tp_as_mapping */

0, /* tp_hash */

(ternaryfunc)type_call, /* tp_call */

0, /* tp_str */

(getattrofunc)type_getattro, /* tp_getattro */

(setattrofunc)type_setattro, /* tp_setattro */

0, /* tp_as_buffer */

Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |

Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TYPE_SUBCLASS, /* tp_flags */

type_doc, /* tp_doc */

(traverseproc)type_traverse, /* tp_traverse */

(inquiry)type_clear, /* tp_clear */

0, /* tp_richcompare */

offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */

0, /* tp_iter */

0, /* tp_iternext */

type_methods, /* tp_methods */

type_members, /* tp_members */

type_getsets, /* tp_getset */

0, /* tp_base */

0, /* tp_dict */

0, /* tp_descr_get */

0, /* tp_descr_set */

offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */

type_init, /* tp_init */

0, /* tp_alloc */

type_new, /* tp_new */

PyObject_GC_Del, /* tp_free */

(inquiry)type_is_gc, /* tp_is_gc */

};

到此为止,我们已经了解了每隔类型的内建函数 int() 、float() 的创建过程,也知道了 type() 函数第一次的返回值

PyObject_VAR_HEAD

接下来我们所要了解的是,为什么

>>> type(int)

>>> type(object)

>>> type(type)

这就涉及到 type() 函数的实现了,我们知道,PyType_Type 、PyBaseObject_Type 和 PyLong_Type 都是的成员变量 tp_base 都是 0 ,也就是说它们都没有基类

但是大家有没有发现另一个有趣的成员变量,就是 PyObject_VAR_HEAD

可以说,几乎所有的类型都有这个成员变量,它,就是继承链条,它用于表示当前类型在所有继承体系中的为止

我们来看看它的实现

Include/object.h

#define PyObject_VAR_HEAD PyVarObject ob_base;

而这个成员变量的初始化方式都是

PyVarObject_HEAD_INIT(&PyType_Type, 0)

也就是说,PyObject_VAR_HEAD 实际上是 PyVarObject 的一个实例

那 PyVarObject 又是什么呢?

typedef struct {

PyObject ob_base;

Py_ssize_t ob_size; /* Number of items in variable part */

} PyVarObject;

PyVarObject 包含了一个 PyObject 的实例,那么 PyObject 又是什么呢?

typedef struct _object {

_PyObject_HEAD_EXTRA

Py_ssize_t ob_refcnt;

struct _typeobject *ob_type;

} PyObject;

看到这,是不是很明朗了,struct _typeobject 就是 PyTypeObject

而 _PyObject_HEAD_EXTRA 的实现如下

#define _PyObject_HEAD_EXTRA \

struct _object *_ob_next; \

struct _object *_ob_prev;

所以,这条继承链就很清楚了,也能理解为什么 type(int)==type(type) 了

Python 中所有的对象,都是由此而成,可能你很费解,那么 int 和 object 其实没有任何的,对吧,我们再下一章节再来学习

在python中、处理的一切都是对象_Python 3+ 一切都是对象相关推荐

  1. python调用shell命令-在Python中执行shell命令的6种方法,你都知道吗?

    原标题:在Python中执行shell命令的6种方法,你都知道吗? Python经常被称作"胶水语言",因为它能够轻易地操作其他程序,轻易地包装使用其他语言编写的库.今天我们就讲解 ...

  2. python中可迭代对象是什么意思_python中可迭代对象是什么

    python中可迭代对象是:存储了元素的一个容器对象,且容器中的元素可以通过"__iter__( )"方法或"__getitem__( )"方法访问.可迭代对象 ...

  3. python中各种@property、@xxx.setter、@classmethod、@staticmethod 都是些啥啊?

    时不时看到有友友对一些 Python 方法的定义感到疑惑:为啥要在方法上面要各种 @ ? 类似这样: 这是你最常见的几个玩意了吧,它们都是啥意思,以及怎么去定义使用呢? 那么,接下来我就尽量通熟易懂的 ...

  4. python中执行linux命令(调用linux命令)_Python调用Linux bash命令

    import subprocess as sup  # 以下注释很多(为了自己以后不忘), 如果只是想在python中执行Linux命令, 看前5行就够了 # 3.5版本之后官方推荐使用sup.run ...

  5. python中for语句可以有else部分_Python中的for...else语句可以不写else吗?

    学习过程中遇到这个问题来交流下. 首先我们来看这个循环: for i in range(1,6): for k in range(1,i): print (k,end='')#可以设置end参数为空字 ...

  6. python中的成员运算符用于判断什么_Python之运算符

    原标题:Python之运算符 这章我们介绍如何用Python的运算符,大家不懂的地方可以加群:579817333咨询学习 Python运算符包括赋值运算符.算术运算符.关系运算符.逻辑运算符.位运算符 ...

  7. python中变量的作用域有几种_Python中变量的作用域(variable scope)

    http://www.crifan.com/summary_python_variable_effective_scope/ 解释python中变量的作用域 示例: 1.代码版 #!/usr/bin/ ...

  8. python中不能使用索引运算的是_Python数据分析之Pandas库(笔记)

    Pandas数据结构 pandas有两个基本的数据结构:Series和DataFrame. 1.1 创建Series数据 需要引入pandas模块:import pandas as pd 需要引入Se ...

  9. python中四种进制的输出_Python基础语法和进制

    基础语法 开发种常用的快捷键 键位 功能 ctrl + / 添加注释和取消注释 ctrl + s 保存 ctrl + c 复制 ctrl + v 粘贴 ctrl + x 剪切 ctrl + z 撤销 ...

最新文章

  1. java监听组合按键_js监听组合按键
  2. 《强化学习周刊》第16期:多智能体强化学习的最新研究与应用
  3. SAP PM 入门系列4 - 如何手工触发一个新的PM检验批?
  4. java socket nio 阻塞_Java NIO实现非阻塞式socket通信
  5. Linux之环境变量
  6. mysql查找大小写_mysql查询不区分大小写
  7. Angular实现图片点击缩放组件
  8. PHP随机静态页面生成系统源码雨尘SEO系统
  9. 机器人多用途综合官网展示PHP单页源码
  10. sql中替换逗号为换行符_使用T-SQL将逗号或其他定界符转换为SQL Server中的表或列表
  11. 从没见过干净图片,英伟达AI就学会了去噪大法 | ICML论文
  12. 报错解决:symbol lookup error-----undefined symbol: JLI_StringDup
  13. VFX - Niagara中的Emitter Summary
  14. 用K-means聚类分类不同行业的关税模型
  15. AppleID忘记密保问题,同时未开启双重认证,需要签署新的协议才能进行下载或者开发的情况处理
  16. 回炉再造Css Layout
  17. 使用echarts中国地图添加气泡时使用接口访问的数据不显示
  18. win7 linux终端模拟器,SecureCRT(终端仿真器)
  19. iconfont多次下载合并
  20. 8051单片机的C语言编程

热门文章

  1. Linux的centos永久关闭防火墙的命令
  2. CSS的display:table-cell:多行文字的垂直居中水平居中
  3. PHP登录密码的生成与验证
  4. PHP的JSON封装
  5. springboot @value启动报错_打造一个 Spring Boot 注解启动控制开关
  6. android aar项目_介绍如何调试Xamarin.Android的binding项目
  7. html中的高和宽背景色怎么写,css background-size与背景图片填满div
  8. 【若依(ruoyi)】layui upload
  9. springboot 注解动态赋值_java springboot动态给注解属性参数赋值
  10. java 字符串赋值_灵魂拷问:为什么 Java 字符串是不可变的?