《Python源码剖析》之PyTypeObject

前言

这一篇博客原本应该是写在上一篇关于pyObject对象的博客中的,但是为了不把内容写的又臭又长,给读者减轻痛苦,给我也减少压力,于是就专门用一篇介绍一下今天的主角—pyTypeObject。

开始

还记得在上一篇我们有聊到,pyObject的结构体很简单,总共只有三项,其中一项就是类型为pyTypeObject的变量ob_type
image.5baf5f54fee311eebf312b20f7a91591.png
这个被遗留的小东西,看似简单,但实际上却承载了非凡的使命!我们都知道python是面向对象的编程语言,之前我们一直在探究对象层面的东西,但是我们要知道,得到一个对象的前提是需要有类[型]的,不然我怎么知道这是一个什么对象?在不知道它是一个什么对象的前提下,就更不会知道它会有什么行为或者属性…而pyTypeObject的的存在就是为了解决这些问题,我认为它在某种意义上来说,就是面向对象中的含义的具体实现!

来看看它的具体定义吧!内容看起来有点多,我这里就只截取部分出来:

image.5092e382fee511eebf312b20f7a91591.png

// If this structure is modified, Doc/includes/typestruct.h should be updated
// as well.
struct _typeobject {PyObject_VAR_HEADconst char *tp_name; /* For printing, in format "<module>.<name>" */Py_ssize_t tp_basicsize, tp_itemsize; /* For allocation *//* Methods to implement standard operations */destructor tp_dealloc;Py_ssize_t tp_vectorcall_offset;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 */PyMethodDef *tp_methods;PyMemberDef *tp_members;PyGetSetDef *tp_getset;// Strong reference on a heap type, borrowed reference on a static typePyTypeObject *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;vectorcallfunc tp_vectorcall;
};

根据它的变量名,结合它的注释是不是看起有点亲切的样子,比如说第一个变量tp_name,它给出的解释是为了格式化打印,我们来动手打印几个类型试试:image.97d68f98fee811eebf312b20f7a91591.png
发现确实前面是模块,后面是具体的名这样的格式!不知道这样会不会让你对这个源码会有一点亲切感,仿佛找到了python它的老家哈哈🤓🤓
当然还有其他很多变量,比如:tp_getattrtp_setattr,其实我们平常调用的getattr和setattr就是他俩;tp_hash,我们调用hash函数时实际上执行的就是这个;tp_mro方法的调用顺序等等,可以在这里好好的和python叙叙旧哈哈

python中的三大类型

又到了分类的时间了哈哈哈,之前我们按照对象的长度是否可变可以分为变长对象和不可变长对象,这次,我们分类的准则是:对象的行为。这个听起来也许有点抽象,简单来说就是:我们可以把具有相似行为和属性的一些对象归为一类。又让我联想到了鸭子🦆类型的定义哈哈哈

我们来看一个具体的例子:
python中的int和float对象,int对象可以进行加减乘除,乘方,开方等等一系列的数学运算行为;而float对象也可以进行加减乘除等等一系列的数学运算,那么我们就可以把它们归为一类,因为它们的行为高度相似!
:::info
面向对象中类的一个概念:类是对象行为的高度抽象。这个听起来比较抽象,感觉有一种编程哲学的感觉🤣,但是其实就是上面的意思。(个人观点,不知道你赞不赞同)

:::
在python中,根据对象的行为,定义了最基本的三大类型,它们分别是:tp_as_numbertp_as_sequencetp_as_mapping,分别对应的就是number(数字),sequence(序列)和mapping(映射)。而这个定义就被包含在了pyTypeObject的结构体中:
image.26a8a356feed11eebf312b20f7a91591.png
因此,我们可以说,pyTypeObject肩负的责任真的不容小觑!接下来,我们再来看看它是如何具体实现的。
image.aed9b8cafef011eebf312b20f7a91591.png

具体到每一个类型的结构体内部,可以发现,其实就是定义(抽象)了每一个类型下最基本的方法,那么何时何地去实现的这些方法呢?还记得我们刚开始说python的源码组织那篇博客吗?通过它,我们可以知道,python中所有内置对象的定义都包含在了Objects这个目录下,我们可以在这个目录中寻找到float对象类型的定义如下:
image.46638d46fef211eebf312b20f7a91591.png
首先,它定义了一个PyNumberMethods类型的float_as_number,也就是我们上面说的number类型,同时它在内部实现了add,sub,mul等一些基本的运算方法,然后在定义float类型PyFloat_Type时直接引用float_as_number地址,这样就get了作为number类型的一些基本行为,有了这些行为,我们就可以说它是一个number类啦!或者,在这里我们可以更加具体的一点说,它就是具有number行为的float类型啦!

同理,如果你感兴趣的话,你也可以继续去探究int,list,tuple,dict,str等其他的python内置对象,你肯定会发现,这些内置对象也一定属于这三大类型中的其中一种!加油,去开启你的探索吧!

总结

通过对pyTypeObject的探究,我们可以知道,每一个对象都会有一个自己的pyTypeObject,因为它们都会有自己的类;在pyTypeObject结构体内部它定义了三大类型numbersequencemapping各自的结构体,可以理解成最基本的行为集合,通过实现其中任何一种类型中全部或部分的行为定义,就可以实现一个具体的类,以float类型为例,我们只需要实现number结构体中的加减乘除等一系列的行为,那么我就可以认为它是一个number类型,同时它也是python中一个具体的类型了,以此类推,python中的int,str,list,dict等类型的实现也是如此,有了这些基本的类型,就足以构建起python中面向对象最基本的类型生态了!

更多内容可以关注博主的个人博客系统:《Python源码剖析》之PyTypeObject

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/2855.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

具身智能的 Scaling Law

Scaling Law 具身智能的Scaling Law指的是一种理论&#xff0c;它探讨了具备智能的生物或机器系统随着规模的扩展而表现出的一些规律性变化。这个理论涵盖了许多方面&#xff0c;主要关注智能系统的不同尺度之间的相互关系。 具身智能是指生物或机器系统在其环境中感知、行动…

vscode 使用文件模板功能来添加版权信息

vscode 新建文件的时候&#xff0c;自动填充作者及版权信息 无需使用插件&#xff0c;操作如下&#xff1a; 选择 “首选项(Preferences)”。在搜索框中输入 “file template” 或者 “文件模板”&#xff0c;然后选择相关的设置项。 {"C_Cpp.clang_format_fallbackSt…

嵌入式虽然入门容易,但精通难度很大。

在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;此外&#xff0c;嵌入式系统的…

蓝桥杯——分巧克力

思路非常简单&#xff0c;就是一个二分法。 注意一下l和r的取值&#xff0c;就可以了。 // 如何进行切分巧克力&#xff1a;横纵除法。例如&#xff1a;一块6*5的&#xff0c;欲切为3*3的小块&#xff0c;横&#xff1a;6/2 3&#xff1b;纵&#xff1a;5/31.所以可以切成3*…

职业技能鉴定服务中心(新闻系统+证书查询系统)

后端采用ThinkPHP8&#xff0c;最新tp框架 前端采用divcss布局 数据库采用MySQL 采用三种技术实现新闻系统和证书查询系统 源码&#xff1a;git clone https://gitee.com/3539949703/certificate-website.git 效果图如下&#xff1a;

【ZZULIOJ】1078: a+b(多实例测试1)(Java)

目录 题目描述 输入 输出 样例输入 Copy 样例输出 Copy 提示 code 题目描述 计算AB 输入 输入第1行为一个整数n(1≤n≤10)&#xff0c;代表测试的组数。 下面有n组测试数据&#xff0c;每组1行&#xff0c;为2个整数&#xff0c;为A, B。 输出 对每行输入&#xff…

采用ModelSim创建一个简单的实例

参考这个链接&#xff1a;modelsim的详细使用方法和容易出现的问题&#xff01;&#xff08;适用初学者&#xff09;-CSDN博客

[Linux_IMX6ULL驱动开发]-设备树简述

目录 设备树的引入 设备树具体框架 设备树的属性 label address-cells和size-cells compatible model status reg 设备树的编译 内核对设备树的处理 plateform_device如何对应plateform_driver 设备树的引入 之前已经学习了解过了总线驱动模型的概念&#xff0c;也…

webots学习记录8:R2023b如何在某个零件上添加一个恒定的力(矩)

在webots安装路径下&#xff0c;从include\controller\c\webots\supervisor.h中可以看到如下定义&#xff1a; void wb_supervisor_node_add_force(WbNodeRef node, const double force[3], bool relative); void wb_supervisor_node_add_force_with_offset(WbNodeRef node, c…

37-5 基于时间的盲注 SQL 注入 PoC 的 Python 编写

攻击目标就用sql靶场的第9关,手注与靶场搭建:22-5 SQL注入攻击 - 基于时间的盲注-CSDN博客 poc import concurrent.futures # 导入并发模块 import requests # 导入发送HTTP请求的库 import string # 导入处理字符串的库url = "http://127.0.0.1/sqli-labs-master…

AndroidStudio中虚拟机(AVD)无法启动,出现unable to locate adb错误

1.检查Android SDK Platform-Tools是否安装(个人是通过这个方法解决的) 首先通过File-Project Structure-Project SDK检查SDK有没有被选中 步骤&#xff1a;打开file -> settings &#xff0c;搜索SDK 之后点击"-",在点击Apply进行安装 2.可能是驱动的问题 电脑…

关于大模型训练微调的几个概念

什么是训练、预训练、微调&#xff1f; Post-pretrain、SFT、RLHF 是什么&#xff1f;有什么区别&#xff1f;RAG 与微调有什么区别&#xff1f;什么场景下需要微调&#xff1f;微调需要多少数据&#xff1f; 成本如何&#xff1f; 1、训练 总结来说&#xff0c;预训练是为了…

深入解析YOLOv2

深入解析YOLOv2 引言 目标检测是计算机视觉中的一个核心问题&#xff0c;它旨在识别图像中所有感兴趣的目标&#xff0c;并给出它们的类别和位置。近年来&#xff0c;随着深度学习技术的发展&#xff0c;目标检测领域取得了巨大的进步。YOLO&#xff08;You Only Look Once&a…

基于OSAL 实现UART、LED、ADC等基础示例 4

1 UART 实验目的 串口在我们开发单片机项目是很重要的&#xff0c;可以观察我们的代码运行情况&#xff0c;本节的目的就 是实现串口双工收发。 虽然说 osal 相关的代码已经跟硬件关系不大了&#xff0c;但是我们还是来贴出相关的硬件原理图贴出来。 1.1 初始化 osal_init_s…

交换式网络捕获网络流量的方法

交换式网络捕获网络流量的方法 参考资料&#xff1a; https://blog.csdn.net/weixin_44143678/article/details/107559329 # 一.端口镜像 端口镜像&#xff0c;又称为“端口监视”或“端口抄送”&#xff0c;是一种网络管理技术&#xff0c;旨在将网络设备上的特定端口的流…

PyTorch Conv2d 前向传递中发生了什么?

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

Servlet对象的生命周期

1.什么是Servlet的生命周期? Servlet对象什么时候被创建&#xff0c;神魔时候被销毁。 Servlet对象创建了几个? Servlet对象的生命周期表示&#xff1a;一个 Servlet对象从出生在最后死亡&#xff0c;整个过程是怎样的。 Servlet对象由随来维护&#xff1f; Servlet对象的…

[Java、Android面试]_19_单例模式(高频问题)

本人今年参加了很多面试&#xff0c;也有幸拿到了一些大厂的offer&#xff0c;整理了众多面试资料&#xff0c;后续还会分享众多面试资料。 整理成了面试系列&#xff0c;由于时间有限&#xff0c;每天整理一点&#xff0c;后续会陆续分享出来&#xff0c;感兴趣的朋友可关注收…

设计模式:解释器模式

定义 解释器模式&#xff08;Interpreter Pattern&#xff09;是一种行为型设计模式&#xff0c;它给定一个语言&#xff0c;定义它的文法的一种表示&#xff0c;并定义一个解释器&#xff0c;这个解释器使用该表示来解释语言中的句子。简单来说&#xff0c;它主要用于某些特定…

Springboot的日常操作技巧

文章目录 1、自定义横幅2、容器刷新后触发方法自定义3、容器启动后触发方法自定义**CommandLineRunner**ApplicationRunner 不定时增加 参考文章 1、自定义横幅 简单就一点你需要把banner.text放到classpath 路径下 &#xff0c;默认它会找叫做banner的文件&#xff0c;各种格式…