Python中一切皆对象,包括实例对象和类型对象,如整数、浮点数、字符串是实例对象,整数类型、浮点数类型、字符串类型是类型对象。

# [Python]
>>> n=10
>>> type(n)
<type 'int'>
>>> type(int)
<type 'type'>

>>> sys.getsizeof(n)
  20
  >>> sys.getsizeof(int)
  444
  >>>

  如演示代码所示,整数对象(n)的类型是int(整数类型),整数类型对象的类型是type(类型对象);其中整数对象占用20字节内存,而整数类型对象占用444字节内存[这些数值取决于测试所使用的设备和系统]

  看到占用内存的数值大小,一定会非常好奇这些内存用来做什么,后面会贴源码来进行说明。对象是数据以及基于这些数据的操作的集合,在Python中对象一旦被创建,其在内存中的大小就固定不变。

  

  PyObject

  PyObject是对象系统的核心,所有的对象都包含这部分数据。它主要包括:用于内存管理的引用计数(ob_refcnt)、类型对象指针(ob_type)、堆内存中对象管理用的双向链表指针(_ob_next, _ob_prev)[总共16字节]。

  其中ob_type指向对象所属的类型对象,而类型对象是有定义操作集合的,所以在运行时通过ob_type找到合适的操作(函数调用),实现了Python的动态机制。

// [C]
typedef struct _object {
struct _object *_ob_next;
struct _object *_ob_prev;
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;

  PyVarObject

  同一类型的对象占用的内存大小并非相同的,如字符串对象,依据字符串长度占用的内存大小不同,所以这种变长对象用PyVarObject结构体来表示。当然也有一些类型对象是定长的,如整数对象、浮点数对象。

// [C]
typedef struct {
PyObject_HEAD // PyObject数据部分
Py_ssize_t ob_size; // 大小
} PyVarObject;

  相对于PyObject,定长对象只增加了变长对象的大小字段(ob_size)。

  PyObject和PyVarObject的数据中,都有指向类型对象的指针,类型对象是_typeobject结构体,即PyTypeObject。

  

  PyTypeObject

  类型对象也包含实例对象的数据部分(引用计数、类型对象指针,对象双链表指针),它包含的更多字段是适用于此类型的操作。比如:

  标准操作:释放内存(tp_dealloc)、打印(tp_print)、获取属性(tp_getattr)、设置属性(tp_setattr)、比较(tp_compare)。

  数值对象操作集合(tp_as_number)、序列对象操作集合(tp_as_sequence)、关联对象操作集合(tp_as_mapping)等[限于篇幅省略了很多字段]。

// [C]
typedef struct _typeobject {
PyObject_VAR_HEAD
const char *tp_name; // 类型名
Py_ssize_t tp_basicsize, tp_itemsize; // 内存分配 // 标准操作
destructor tp_dealloc;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
cmpfunc tp_compare;
reprfunc tp_repr; PyNumberMethods *tp_as_number; // 数值对象应该支持的操作
PySequenceMethods *tp_as_sequence; // 序列对象应该支持的操作
PyMappingMethods *tp_as_mapping; // 关联对象应该支持的操作 ...
} PyTypeObject;

  注:像cmpfunc是定义的函数指针,其它的函数指针也有类似的定义。

    typedef int (*cmpfunc)(PyObject *, PyObject *); // 比较两个PyObject对象的函数指针

  

  在Python中,一般来说对象是不能被静态初始化的也不能在栈空间生存。但内建的类型对象都是被静态初始化的,如PyInt_Type、PyFloat_Type、PyString_Type等,其中PyInt_Type的初始化代码如下:

// [C]
PyTypeObject PyInt_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)   // ob_type == &PyType_Type
"int",
sizeof(PyIntObject),
0,
(destructor)int_dealloc, /* tp_dealloc */
(printfunc)int_print, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
(cmpfunc)int_compare, /* tp_compare */
(reprfunc)int_to_decimal_string, /* tp_repr */
&int_as_number, /* tp_as_number */
...
};

  注:PyType_Type是类型的类型。

  说完了内建类型,那自定义类型在Python是如何表示的呢?

  自定义class演示代码如下:

# [Python]
>>> class A(object):
... def __init__(self):
... pass
...
>>> A.__class__
<type 'type'>
>>> type.__class__
<type 'type'>

  可以看到自定义class的类型对象是PyType_Type,即用PyType_Type对象来创建自定义类型对象。

  PyType_Type的初始化代码如下:

// [C]
PyTypeObject PyType_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) // ob_type == &PyType_Type
"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_compare */
(reprfunc)type_repr, /* tp_repr */
0, /* tp_as_number */
...
};

  自此把实例对象、类型对象基本讲清楚了,至于具体类型的特性、操作则需要后续再具体讲解。

  

CPython-对象/类型系统的更多相关文章

  1. javascript中15种原生对象类型系统综述

    前面的话 在编程语言中,能够表示并操作的值的类型称做数据类型,编程语言最基本的特性就是能够支持多种数据类型.javascript拥有强大的类型系统,主要包括原生对象.宿主对象和浏览器拓展对象,本文主要 ...

  2. 基于类型系统的面向对象编程语言Go

    (整理自网络) 面向对象编程 Go语言的面向对象编程(OOP)非常简洁而优雅.说它简洁,在于它没有了OOP中很多概念,比如:继承.虚函数.构造函数和析构函数.隐藏的this指针等等.说它优雅,是它的面 ...

  3. javascript中的null,对象系统还是非对象系统?

    1.一直以来的认知 在我学习js的过程中,爱民老师的绿皮书里将js的类型系统分成了两类: 其一是元类型系统:由typeof运算来检测 其二是对象类型系统:是元类型的object的一个分支 而null这 ...

  4. 采访ServiceStack的项目领导Demis Bellot——第1部分(网摘)

    ServiceStack是一个开源的.支持.NET与Mono平台的REST Web Services框架.InfoQ有幸与Demis Bellot深入地讨论了这个项目.在这篇两部分报道的第1部分中,我 ...

  5. js:语言精髓笔记12--动态语言特性(2)

    对于括号内: 通过赋值时发生的重写: (Object1 = function() {}).prototype.value = 100; var obj1 = new Object1; console. ...

  6. 采访ServiceStack的项目领导Demis Bellot——第1部分(转)

    ServiceStack是一个开源的.支持.NET与Mono平台的REST Web Services框架.InfoQ有幸与Demis Bellot深入地讨论了这个项目.在这篇两部分报道的第1部分中,我 ...

  7. JS数据类型的理解(猜测)

    Js 数据类型 对于这个主题,首先来看几个问题,如果你对这几个问题很清楚的话,那就请直接跳过吧,不用接着往下看了,如果不清楚,建议你还是看看. 1)如果判断函数?function 和object的联系 ...

  8. Qt经典—线程、事件与Qobject(耳目一新)

    介绍 You’re doing it wrong. — Bradley T. Hughes 线程是qt channel里最流行的讨论话题之一.许多人加入了讨论并询问如何解决他们在运行跨线程编程时所遇到 ...

  9. 【转】Qt事件循环与线程 二

    转自:http://blog.csdn.net/changsheng230/article/details/6153449 续上文:http://blog.csdn.net/changsheng230 ...

  10. Python源码剖析之准备工作

    一个Python程序开发者, 也是C语言爱好者, 为了加强自己对Python语言实现的理解, 最近选择阅读下陈儒老师的书, 对Python3.5.1源码进行阅读, 再次记录下读书笔记.  一.Pyth ...

随机推荐

  1. vue-cli-service & @vue/cli-service

    vue-cli-service & @vue/cli-service https://www.npmjs.com/package/@vue/cli-service https://yarnpk ...

  2. FTP 与 SSH 的安全性对比, 以及FTP,SSH,SFTP,SCP 的关系简单解析!

    FTP 与 SSH 的安全性对比? ftP: http://baike.baidu.com/subview/369/6149695.htm TCP/IP协议中,FTP标准命令TCP端口号为21,Por ...

  3. UTC 时间转换 All In One

    UTC 时间转换 All In One http://www.timebie.com/cn/stduniversal.php UTC 时间 世界的每个地区都有自己的本地时间,在 Internet 及无 ...

  4. Prometheus Monitoring Solution

    Prometheus Monitoring Solution 普罗米修斯 https://prometheus.io/ 警报 监控 增强指标和警报 领先 开源监控解决方案 https://promet ...

  5. set CSS style in js solutions All In One

    set CSS style in js solutions All In One css in js set each style property separately See the Pen se ...

  6. WebAR in Action

    WebAR in Action WebAR (Web + AR) 增强现实 https://developer.mozilla.org/en-US/docs/Web/API/WebAR_API Web ...

  7. queueMicrotask & microtask

    queueMicrotask & microtask microtask microtask queue Promise Mutation Observer API MutationObser ...

  8. 「NGK每日快讯」12.21日NGK第48期官方快讯!

  9. Python学习笔记_类

    class Animal(object): # 定义父类animal def __init__(self,name,sound): # 初始化属性 name sound self.name = nam ...

  10. 12_MySQL如何对查询结果进行排序

    本节所涉及的sql语句: -- 排序关键字 SELECT empno,ename,hiredate FROM t_emp ORDER BY hiredate DESC; -- 排序字段相同的情况 SE ...