• 2.1.6 面向对象:一切皆对象(Python)


    本文来自异想之旅公开发布的Python教程,原文地址:https://www.yuque.com/yxzl/python

    表象展示

    Python 是一门面向对象的程序设计语言,它的设计理念之一便是“一切皆对象”。

    一个最简单的字符串就是一个str类的对象:

    a = 'abc'
    print(type(a))  # 
    
    • 1
    • 2

    我们可以对a进行upper()等操作,因为str类实现了这些方法:

    a = 'abc'
    print(a.upper())  # ABC
    
    • 1
    • 2

    事实上,Python 的基础数据类型全部是类:

    print(str, int, float, bool, list, dict)
    #      
    
    • 1
    • 2

    甚至包括作为关键字的True也是bool类的对象:

    print(type(True))  # 
    
    • 1

    就连函数也难逃一劫:

    def f():
        ...
    
    print(type(f))  # 
    
    • 1
    • 2
    • 3
    • 4

    看,到处都是class

    原理刨析

    新手不友好,看不懂请快跑

    先看看下面朴而不素的代码:

    class F:
        ...
    
    class A(F):
        ...
    
    class B(F, object):
        ...
    
    a = A()
    
    print(F.__bases__)  # (,)
    print(A.__bases__)  # (,)
    print(B.__bases__)  # (, )
    print(object.__bases__)  # ()
    print(type(a))  # 
    print(type(A))  # 
    print(type(object))  # 
    print(type.__bases__)  # (,)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    通过上面的很简单的代码,运用一眼洞穿法,我们可以根据每个打印语句的结果得到一些简单的观察结论:

    1. 如果定义一个类时没有指定继承哪个类,则默认继承**object**
    2. **object**类的父类为空,说明**object**类位于继承关系链的顶端,**object**类是 Python 中所有类的父类,可以说**object**是 Python 中的顶端类
    3. 对象a由类A实例化而来,a的类型为A,这个比较容易理解
    4. 根据 3 的观察结果,同样的观察手法运用在类A上,观察到类A是由type这个类实例化而来,类A的类型为type,说明**A**是一个类的同时也是一个对象(类A是类type的实例化对象)。这里可能有点晕但是请先接着看下去吧
    5. 根据 3 的观察结果,同样的观察手法运用在顶端类object上,观察到object这个顶端类也是由type这个类实例化而来,类object的类型也为type,也说明object作为一个类的同时也是一个对象
    6. **type**作为实例化类**A**和类**object**的类,其父类为**object**

    看完上面的这些观察结论,相信有一部分童鞋已经两眼发懵了,什么类A是一个类也是一个对象,object类的类型是type,而type类的父类又是object……

    这里先来一张图简单表示一下这几者的关系,舒缓一下情绪:

    在这里插入图片描述

    蓝色箭头由实例对象指向实例化它的类,红色箭头由子类指向父类。

    值得注意的是,这个图有几个关键的地方:

    • 类(如class A, class object)都是由type这个类实例化而来的,即所有类(class)对象的类型都是type
    • type这个类也是由type自己实例化而来的(图中type处指向自身的部分),即type类的类型也为type
    • type类的父类是object

    有了以上的铺垫,我们可以知道一个最普通的实例对象链是这样子的:

    type --实例化--> object --衍生(继承)--> class A (类) --实例化--> a(具体对象)

    这部分都是比较好理解的,但关键的问题是——**object**类作为**type**类的父类,怎么会是由**type**类实例化出来的?还有**type**类居然是由**type****自己实例化出来的?**这都是什么操作?

    我们可以看看在源码中,type类和object类分别是什么(Python 的底层是 C 的实现,下面的源码如果看不懂的话请别在意,因为不妨碍理解):

    在源码中,type类的定义如下:

    #define PyVarObject_HEAD_INIT(type, size)
        1, type, size,
    
    PyTypeObject PyType_Type = {
        PyVarObject_HEAD_INIT(&PyType_Type, 0)
        "type",                                     /* tp_name */
        sizeof(PyHeapTypeObject),                   /* tp_basicsize */
        sizeof(PyMemberDef),                        /* tp_itemsize */
        0,                                          /* tp_base */
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    object类的定义如下:

    PyTypeObject PyBaseObject_Type = {
        PyVarObject_HEAD_INIT(&PyType_Type, 0)
        "object",                                   /* tp_name */
        sizeof(PyObject),                           /* tp_basicsize */
        0,                                          /* tp_itemsize */
        0,                                          /* tp_base */
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这两个类结构体中的各项的具体含义这里不做深究,因为不在本文研究范围内。我们只需要关注这两个结构中的第一行:PyVarObject_HEAD_INIT(&PyType_Type, 0)。它表示这个类结构的对象类型。能看出来object类 和 type类的对象类型都是&PyType_Type,而PyType_Type正是底层表示type类的结构体!

    这两个结构体就说明了:object类将类型(即谁实例化了这个类)设置成了type类,type类将类型设置成了自己!这其实是 Python 底层实现的一个小小的 trick ~

    然后在type类的初始化过程中,执行了如下代码:

    type->tp_base = &PyBaseObject_Type;
    
    • 1

    转换为 Python 为:

    type.__base__ = (object, )
    
    • 1

    这句话显式地将object类指定为type类的父类,这不就是第一个问题的答案所在吗?

    源码看到这里,前面的两个问题就已经全部解决了,我们可以开始全面总结一下type``class``object的关系了:

    • object类是所有类(class)的父类,包括type类,object类的父类为空
    • type类是所有类的类型,即为所有类(class)都可由type实例化而来,包括type类自己

    将上面的关系总结成一张图就是:

    在这里插入图片描述

    梅开二度了,那么也还是再提醒一下:蓝色箭头由实例对象指向实例化它的类,红色箭头由子类指向父类。

    不理解的可以再看另一个作者的图:实线箭头表示继承关系,由子类指向父类;虚线箭头表示实例化,由实例对象指向实例化它的类。

    在这里插入图片描述


    后半部分参考和转载自:

  • 相关阅读:
    Docker之介绍与安装
    前端基础入门之JS 事件对象 滚轮事件与键盘事件
    CDH集群集成外部Flink(改进版-与时俱进)
    微服务架构 | 超时管理
    使用printJS插件打印
    ArrayUtils使用
    TCO-PNB ester,1438415-89-4, 反式环辛烯-对硝基苯
    【自然语言处理】【文本生成】BART:用于自然语言生成、翻译和理解的降噪Sequence-to-Sequence预训练
    书签栏(个人)
    CommonsCollection4反序列化链学习
  • 原文地址:https://blog.csdn.net/weixin_44495599/article/details/126184866