Python类型对象举例

作者: ringawho | 来源:发表于2019-04-01 18:20 被阅读0次

    查看之前的PyObject以及PyVarObject结构,我们会发觉它十分简单,甚至简单的不像话,可能我们会想明明在Python中学的是基类是object,有着各种各样的属性

    ['__class__', '__delattr__', '__dir__', ...... ,'__setattr__', '__sizeof__', '__str__']
    

    但是在PyObject中却什么都看不到,其实是有的,只不过是放在了ob_type里面,它是struct _typeobject指针,也就是PyTypeObject指针,我们来看一下Python中的object所对应的ob_type

    Objects/typeobject.c
    // 只列出一部分,剩余部分还涉及其它东西,没有看呢
    PyTypeObject PyBaseObject_Type = {
        PyVarObject_HEAD_INIT(&PyType_Type, 0)
        "object",                                   /* tp_name */
        object_repr,                                /* tp_repr */
        object_str,                                 /* tp_str */
        PyDoc_STR("object()\n--\n\nThe most base type"),  /* tp_doc */
        ......
    };
    

    它的里面包含了各种各样的信息,比如类的名字,对象占用空间的大小,转换为string的方法,都在它里面,

    • tp_name对应的就是类的名字,当你使用type()函数的时候就会出现类的名字,假设我们将它改为"oo"那么,当在新生成的python解释器运行的时候,就会出现:
    >>> type(object())
    <class 'oo'>
    
    • tp_str对应的是执行str()时调用的,它是一个函数指针,对应的函数如下,可以看出它实际是找到对应的类型对象,然后调用tp_repr指向的函数或者是object_repr,在这里它指的都是
    static PyObject *  object_str(PyObject *self)
    {
        unaryfunc f;
    
        f = Py_TYPE(self)->tp_repr;
        if (f == NULL)
            f = object_repr;
        return f(self);
    }
    
    static PyObject *  object_repr(PyObject *self)
    {
        PyTypeObject *type;
        PyObject *mod, *name, *rtn;
        // ......
        if (mod != NULL && !_PyUnicode_EqualToASCIIId(mod, &PyId_builtins))
            rtn = PyUnicode_FromFormat("<%U.%U object at %p>", mod, name, self);
        else
            rtn = PyUnicode_FromFormat("<%s object at %p>",
                                      type->tp_name, self);
        // ......
        return rtn;
    }
    

    此时对比一下使用str()时的结果,就可以看出它算是怎么做出rtn

    >>> str(object())
    '<object object at 0x00000239682FB0D0>'
    

    人为的在return语句之前自己写一条,就可以出现自己想要的输出了,例如:

    //else语句修改为
    rtn = PyUnicode_FromFormat("<%s object at ???>", "MyObject");
    
    // 输出
    >>> str(object())
    '<MyObject object at ???>'
    
    • 最后一个tp_doc,用到一个宏,但是这个宏其实什么都没做,只是相当于说明一下它是个文档说明的字符串#define PyDoc_STR(str) str,同样的,我们也可以做修改,通过object.__doc__或者建object对象访问__doc__属性就可以看到你的修改结果了

      不过这里有个小问题,显示的时候明明没有object()\n--\n\n这一部分,而且完全删去了也没有任何影响

      于是我找到了这样一行代码,我猜测它所谓的Signature就是指tp_name + '()\n--\n\n',如果只删除其中部分字符,他就没有办法取出Signature,而正常情况下它会去除掉Signature部分,所以只剩下'The most base type'这一句话

      怎么找到的代码是我看了Philip Guo后突然想到的,和我之前介绍的字节码查看有点关系哦,当然,之后会有介绍的

    const char *old_doc = _PyType_DocWithoutSignature(type->tp_name,
                    type->tp_doc);
    

    小小的修改一下,虽然改的东西是最浅显的,但是至少可以知道自己读对了,同时也减少Python解释器源码的神秘感,给自己点信心喽!

    相关文章

      网友评论

        本文标题:Python类型对象举例

        本文链接:https://www.haomeiwen.com/subject/lywmbqtx.html