在Python的学习中咱们确定会听到一句话:「python中一切皆对象」。python
若是再接着学习下去的话,咱们就会接触到Python中的type, object, class等概念。网上也有很多文章阐述了这三者之间的关系,可是在看了大部分文章以后我仍是似懂非懂,感受就像有什么东西卡在了喉咙一直咽下不去同样。web
因而为了能让本身晚上顺利吃上饭,我立马对着搜索引擎就是一顿操做,终于赶在外卖小哥打响我电话以前,咽下了这几个如鲠在喉的概念,舒服!
趁着外卖小哥上楼这会,分享下我学习研究后的理解吧。算法
python做为面向对象的语言之一,符合一切基于面向对象理念的设计。在面向对象的体系中,对象存在着两种关系。后端
简单来讲即子类继承于父类,子类拥有其自身及父类的方法和属性,同名的子类方法和属性将会覆盖父类的方法和属性。
语义化的理解栗子为:「蛇」类继承自「爬行动物类」,因此「蛇是一种爬行动物」,英文说「snake is a kind of reptile」。
在python中的继承关系能够简单表示以下:数据结构
class Reptile:
title = '爬行动物'
def crawl(self):
print(self.title)
class Snake(Reptile):
def crawl_a(self):
print(self.title)
p = Snake()
p.crawl() # 爬行动物
p.crawl_a() # 爬行动物
print(p.title) # 爬行动物
复制代码
上面这个栗子中,子类Snake继承了父类Reptile的title属性和crawl方法,使得类B的实例对象b能调用父类的a属性和get方法。
另外,若是要查看一个类(class)的父类,可使用class_name.__bases__
的形式来查看。app
Snake.__bases__ # (<class '__main__.Reptile'>,)
复制代码
若是继承关系比如父与子的关系,实例化关系则是一个从抽象到具体的过程。实例是某个类中具体的个体的表示。
语义化的理解栗子为:「小p是一条蛇」,「蛇」是一个分类,「小p」则是这个分类中的一个具体的个体。英文说「小p is an instance of snake」。学习
class Snake:
pass
p = Snake() # p是Snake类的实例对象
复制代码
若是想要查看一个对象是由哪一个类实例化而来,可使用type()
或 object_name.__class__
来查看。表示对象属于什么类型。搜索引擎
type(p) # <class '__main__.Snake'> 表示对象p是由类Snake实例化而来,p的类型是Snake
p.__class__ # <class '__main__.Snake'> 表示对象p是由类Snake实例化而来,p的类型是Snake
复制代码
有了以上的基础,咱们就能够一步一步来探究python中对象潜藏着一些秘密了。嘿嘿嘿~ spa
先看看下面朴而不素的代码:.net
class A:
pass
a = A()
print(A.__bases__) # (<class 'object'>,)
print(object.__bases__) # ()
print(type(a)) # <class '__main__.A'>
print(type(A)) # <class 'type'>
print(type(object)) # <class 'type'>
print(type.__bases__) # (<class 'object'>,)
复制代码
经过上面的很简单的代码,运用一眼洞穿法
,咱们能够根据每一个打印语句的结果获得一些简单的观察结论:
A
实例化而来,a的类型为A
,这个比较容易理解。type
这个类实例化而来,类A的类型为type
,说明类A是一个类的同时也是一个对象(类A是类type的实例化对象)。这里可能有点晕可是请先接着看下去吧。object
这个顶端类也是由type
这个类实例化而来,类object
的类型也为type
,也说明object做为一个类的同时也是一个对象。看完上面的这些观察结论,相信有一部分童鞋已经两眼发懵了,什么类A是一个类也是一个对象,object类的类型是type,而type类的父类又是object…blablabla
诶,莫方莫方,俗话说无图言*,这里先来一张图简单表示一下这几者的关系,舒缓一下情绪:
下面咱们就能够开始看图写做文啦~
蓝色箭头由实例对象指向实例化它的类,红色箭头由子类指向父类。值得注意的是,这个图有几个关键的地方:
有了以上的铺垫,咱们能够知道一个最普通的实例对象链是这样子的: type --实例化--> object --衍生--> class --实例化--> a(具体对象)
这部分都是比较好理解的,但关键的问题是 ———— object类做为type类的父类,怎么会是由type类实例化出来的?还有type类竟然是由type本身实例化出来的?这都是什么操做?
我的认为,这两个问题解决了才能更好地理解type、class、object三者的关系。然而要知道为何python是这样设计的,最好的作法即是去翻他们的源码啦。不过在翻以前,其实已经有一些大佬对python的源码作了解读,经过搜索引擎认真找寻即可找到想要的答案。python的底层是C的实现,下面的源码若是看不懂的话请别在乎,由于不妨碍理解。
(⊙o⊙)
咱们能够看看在源码中,type
类和object
类分别是什么: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 */
...
}
复制代码
object
类其实是:
PyTypeObject PyBaseObject_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"object", /* tp_name */
sizeof(PyObject), /* tp_basicsize */
0, /* tp_itemsize */
0, /* tp_base */
...
}
复制代码
这两个类结构体中的各项的具体含义这里不作深究,由于不在本文研究范围内。咱们只须要关注这两个结构中的第一行:
PyVarObject_HEAD_INIT(&PyType_Type, 0)
它表示这个类结构的对象类型。能看出来object
类 和 type
类的对象类型都是 &PyType_Type
,而 PyType_Type
正是底层表示type类的结构体!
这两个结构体就说明了:object
类将类型(即谁实例化了这个类)设置成了type
类,type
类将类型设置成了本身!这实际上是python底层实现的一个小小的trick~
而后在type
类的初始化过程当中,执行了以下代码:
type->tp_base = &PyBaseObject_Type;
复制代码
转换成python为
type.__base__ = (object,)
复制代码
表示将object类指定为type类的父类,这不就是第二个问题的答案所在吗?
源码看到这里,前面的两个问题就已经所有解决了,咱们能够开始全面总结一下type,class,object的关系了。
type,class,object三者关系:
写到这里,python中这三者的关系探究就差很少了,只能说技术写做不是一件容易的事情,先后改了很多东西仍是不那么让本身满意,可是已经按照本身的意思给表述出来了,但愿以后能写得更顺手一些。话说外卖小哥已经在门口等了我5分钟了,写文章死了那么多脑细胞,胃口必定不错吧哈哈。
若是你以为这篇内容对你有帮助,我想邀请你帮我三个小忙: