python源码学习 之 对象创建和对象的行为

巴扎黑
Libérer: 2016-12-07 11:24:37
original
1233 Les gens l'ont consulté

在将对象的创建和行为之前,我们先来看一下类型对象,python是弱类型语言,但并不代表python没有类型,python中处理对象的类型有一个专门的对象,我们称之为类型对象,如果不知道对象的类型就无法为对象开辟内存空间,因为占用内存的大小是对象的元信息,是对象的基本信息,这与对象所属类型密切相关,因此,他一定回出现在python对象所对应的类型对象中,打开python源码中的include文件夹的object.h文件,查看PyTypeObject的源码,在大约第324行: 


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; 
    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__ 
结果如下: 
 
 
实际上,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'] 
运行结果为: 




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 

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal