在将对象的创建和行为之前,我们先来看一下类型对象,python是弱类型语言,但并不代表python没有类型,python中处理对象的类型有一个专门的对象,我们称之为类型对象,如果不知道对象的类型就无法为对象开辟内存空间,因为占用内存的大小是对象的元信息,是对象的基本信息,这与对象所属类型密切相关,因此,他一定回出现在python对象所对应的类型对象中,打开python源码中的include文件夹的object.h文件,查看pytypeobject的源码,在大约第324行:
typedef struct _typeobject {
pyobject_var_head
const 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;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
cmpfunc tp_compare;
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 */
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;
/* added in release 2.2 */
/* 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;
#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;
上面这段代码很长,一个结构体100多行,不过所包含的信息主要分为如下四大类:
1、类型名,tp_name,主要是python内部以及调试时使用,用来识别对象的所属类型;
2、tp_basicsize和tp_itemsize,创建该类对象分配内存空间的大小的信息;
3、与该类对象关联的操作信息,比如说tp_base等指向函数的指针;
4、类型对象的类型信息。
重点1、对象的创建:
python创建对象主要有两种方法,python c api和pyint_type。
python c api让用户从c环境与python交互,一共有两种api,一种是aol(abstract object layer)即泛型api,另一种是col(concrete object layer)即类型api;aol都有pyobject_***的形式,可以应用到任何python对象上,表达式一般表示为:pyobject* intobj = pyobject_new(pyobject,&pyint_type),而col的api一般如下:pyobject* intobj = pyint_fromlong(1000);我们就创建了一个1000整数对象。
无论采用哪种python c api,python都是最终直接分配内存,因为这都是python的内建对象,而如果我们自己定义了一个类如:class myself(object),对于类型myself,python不会使用api来创建,但是python会通过myself所对应的类型对象来创建实例对象,myself的类型对象是object,所有python会通过object来创建myself的实例化对象。我们执行如下代码:
class a(object):
pass
a = a()
type(a)
a.__base__
结果如下:
<class ‘__main__.a’>
<type ‘object’>
实际上,python是先实例化object运行object的构造方法,然后再实例化a,这与python的底层实现有着密切的联系。任何一个用户自定义的python类,最终都有一个共同的父类object,实例化时先实例化object类,一次向下,直到实例化用户自定义的类。
screen shot 2014-06-14 at 下午12.01.15
对象的行为:
在对象的操作信息中有三组非常重要的操作族,tp_as_number,tp_as_sequence,tp_as_mapping,他们分别指向pynumbermethods,pysequencemethods,pymappingmethods函数族。对于一种对象,他可以同时定义三个函数族中的所有操作,即对象可以表现出数值对象的特性和关联对象的特性,代码如下:
class myint(int):
def __getitem__(self,key):
return key+str(self)
a = myint(1)
b = myint(2)
print a+b
print a['key']
运行结果为:
1
2
3
key1
最后说一下类型对象的类型。对象的类型也是一个对象,那么这个对象的类型又是什么呢?首先可以确定他也是一个对象。我们称之为类型的类型。这个十分、非常、很、very much重要,就是源码中的pytype_type结构体,这个在objects文件夹的typeobject.c文件里,源代码如下:
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_compare */
(reprfunc)type_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)_py_hashpointer, /* 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 */
type_richcompare, /* 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 */
};
呵呵,这个看起来很复杂,pyint_type和pytype_type之间如何联系起来的?就是前面博客中所说的引用计数器,一个整数对象运行时如下图所示:
screen shot 2014-06-14 at 下午1.32.09
python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号