Python源码解读之五 对象的多态性和行为

Python源码解读之五 对象的多态性和行为

对象的多态性

Python创建一个对象,比如PyFloatObject,会分配内存并进行初始化。然后内部统一使用泛型指针 PyObject* 来保存和维护这个对象,而不是PyFloatObject *。而不是PyFloatObject *。通过PyObject *保存和维护对象,可以实现更加抽象的上层逻辑,而不用关心对象的实际类型和实现细节。

Py_hash_t
PyObject_Hash(PyObject *V);

该函数可以计算任意对象的哈希值,而不用关心对象的类型是啥,它们都可以使用这个函数。
但是不同的类型对象,行为也是千差万别,哈希值的计算方式也是如此,那PyObject_Hash函数是如何解决这个问题的呢?不用想,因为元信息存储在对应的类型对象中,所以肯定会通过其ob_type拿到指向的类型对象。而类型对象中有一个成员叫tp_hash,它是一个函数指针,指向的函数专门用来计算其实例对象的哈希值。所以我们看一下PyObject_Hash的函数定义,看看它内部都做了什么,该函数位于Object/Object.c中。

Py_hash_t
PyObject_Hash(PyObject *v)
{
   
    /* Py_TYPE是一个宏,用来获取PyObject *内部的ob_type */
    PyTypeObject *tp = Py_TYPE(v);
    /*  获取对应的类型对象内部的tp_hash */
    /*  tp_hash是一个函数指针,对应__hash__ */
    if (tp -> tp_hash != NULL)
        /* 如果tp_hash不为空,证明确实指向了具体的hash函数
         * 那么拿到函数指针之后,通过*获取对应的函数
         * 然后将PyObject *传进去计算哈希值,返回
         */
        return (*tp -> tp_hash)(v);
    
    /* 走到这里说明tp_hash为空,但这存在两种可能
     *  1. 该类型对象可能还未完全初始化, 导致tp_hash暂时为空
     *  2. 该类型本身就不支持其 "实例对象" 被哈希 
     */
    
    /* 如果是第一种情况,那么它的tp_dict(属性字典)一定为空
     * tp_dict是动态设置的,它为空,是类型对象没有完全是初始化的重要特征
     * 但如果tp_dict不为空,说明类型对象一定已经被完全初始化了
     * 所以此时tp_hash要是还为空,就真的说明该类型不支持实例对象被哈希
    */
    if (tp->tp_dict == NULL) {
   
        /* 属性字典为空,那么先进行类型的初始化 */
        if (PyType_Ready(tp) < 0)
            return -1
        /* 然后再看是否tp_hash是否为空,为空的话,说明不支持哈希
         * 不为空则调用对应的哈希函数
         */
        if (tp->tp_hash != NULL)
            return (*tp->tp_hash)(v);
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值