首页 技术 正文
技术 2022年11月19日
0 收藏 793 点赞 3,867 浏览 2868 个字

  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 */
...
};

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

  

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,082
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,557
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,406
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,179
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,815
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898