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

巴扎黑
发布: 2016-12-07 11:24:37
原创
1516人浏览过

在将对象的创建和行为之前,我们先来看一下类型对象,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'] 
运行结果为: 




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在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号