在python中、处理的一切都是对象_Python 3+ 一切都是对象
对于 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+ 一切都是对象相关推荐
- python调用shell命令-在Python中执行shell命令的6种方法,你都知道吗?
原标题:在Python中执行shell命令的6种方法,你都知道吗? Python经常被称作"胶水语言",因为它能够轻易地操作其他程序,轻易地包装使用其他语言编写的库.今天我们就讲解 ...
- python中可迭代对象是什么意思_python中可迭代对象是什么
python中可迭代对象是:存储了元素的一个容器对象,且容器中的元素可以通过"__iter__( )"方法或"__getitem__( )"方法访问.可迭代对象 ...
- python中各种@property、@xxx.setter、@classmethod、@staticmethod 都是些啥啊?
时不时看到有友友对一些 Python 方法的定义感到疑惑:为啥要在方法上面要各种 @ ? 类似这样: 这是你最常见的几个玩意了吧,它们都是啥意思,以及怎么去定义使用呢? 那么,接下来我就尽量通熟易懂的 ...
- python中执行linux命令(调用linux命令)_Python调用Linux bash命令
import subprocess as sup # 以下注释很多(为了自己以后不忘), 如果只是想在python中执行Linux命令, 看前5行就够了 # 3.5版本之后官方推荐使用sup.run ...
- python中for语句可以有else部分_Python中的for...else语句可以不写else吗?
学习过程中遇到这个问题来交流下. 首先我们来看这个循环: for i in range(1,6): for k in range(1,i): print (k,end='')#可以设置end参数为空字 ...
- python中的成员运算符用于判断什么_Python之运算符
原标题:Python之运算符 这章我们介绍如何用Python的运算符,大家不懂的地方可以加群:579817333咨询学习 Python运算符包括赋值运算符.算术运算符.关系运算符.逻辑运算符.位运算符 ...
- python中变量的作用域有几种_Python中变量的作用域(variable scope)
http://www.crifan.com/summary_python_variable_effective_scope/ 解释python中变量的作用域 示例: 1.代码版 #!/usr/bin/ ...
- python中不能使用索引运算的是_Python数据分析之Pandas库(笔记)
Pandas数据结构 pandas有两个基本的数据结构:Series和DataFrame. 1.1 创建Series数据 需要引入pandas模块:import pandas as pd 需要引入Se ...
- python中四种进制的输出_Python基础语法和进制
基础语法 开发种常用的快捷键 键位 功能 ctrl + / 添加注释和取消注释 ctrl + s 保存 ctrl + c 复制 ctrl + v 粘贴 ctrl + x 剪切 ctrl + z 撤销 ...
最新文章
- java监听组合按键_js监听组合按键
- 《强化学习周刊》第16期:多智能体强化学习的最新研究与应用
- SAP PM 入门系列4 - 如何手工触发一个新的PM检验批?
- java socket nio 阻塞_Java NIO实现非阻塞式socket通信
- Linux之环境变量
- mysql查找大小写_mysql查询不区分大小写
- Angular实现图片点击缩放组件
- PHP随机静态页面生成系统源码雨尘SEO系统
- 机器人多用途综合官网展示PHP单页源码
- sql中替换逗号为换行符_使用T-SQL将逗号或其他定界符转换为SQL Server中的表或列表
- 从没见过干净图片,英伟达AI就学会了去噪大法 | ICML论文
- 报错解决:symbol lookup error-----undefined symbol: JLI_StringDup
- VFX - Niagara中的Emitter Summary
- 用K-means聚类分类不同行业的关税模型
- AppleID忘记密保问题,同时未开启双重认证,需要签署新的协议才能进行下载或者开发的情况处理
- 回炉再造Css Layout
- 使用echarts中国地图添加气泡时使用接口访问的数据不显示
- win7 linux终端模拟器,SecureCRT(终端仿真器)
- iconfont多次下载合并
- 8051单片机的C语言编程
热门文章
- Linux的centos永久关闭防火墙的命令
- CSS的display:table-cell:多行文字的垂直居中水平居中
- PHP登录密码的生成与验证
- PHP的JSON封装
- springboot @value启动报错_打造一个 Spring Boot 注解启动控制开关
- android aar项目_介绍如何调试Xamarin.Android的binding项目
- html中的高和宽背景色怎么写,css background-size与背景图片填满div
- 【若依(ruoyi)】layui upload
- springboot 注解动态赋值_java springboot动态给注解属性参数赋值
- java 字符串赋值_灵魂拷问:为什么 Java 字符串是不可变的?