Python类型对象举例

查看之前的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())

  • 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())
''

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

//else语句修改为
rtn = PyUnicode_FromFormat("<%s object at ???>", "MyObject");
// 输出
>>> str(object())
''
  • 最后一个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类型对象举例)