1. 前言
今天主要是学习了 Python 中的对象(object)。编程是一种抽象建模的过程,在 Java 中对象的概念贯彻的非常彻底,每个 Java 类就是一个对象,充分体现了面向对象编程。Python 作为一门高级语言,自然也可以面向对象编程,也可以面向过程编程。了解 Python 的人基本都听说过一句话:Pyhton 中一切皆对象
,老实说,以前我只记得这句话,但是并没有什么见解,仅仅停留在字面上,这不利于自己的成长,对于一名有追求的工程师,吃饭的家伙必须熟悉,因为也就有了这篇文章,这篇文章将介绍:
- Python 中的对象和面向对象中的对象有啥不同?
- Python 中有哪些对象?
- 元类是什么?
- Python 的对象模型
2. 面向对象 VS Python 中的对象
以下摘自 wiki 百科关于面向对象,以及对象和类的描述:
面向对象程序设计(Object-oriented programming,缩写:OOP)是种具有对象概念的程序编程典范,同时也是一种程序开发的抽象方针。类(Class):定义了一件事物的抽象特点。类的定义包含了数据的形式以及对数据的操作。对象是类的实例化。
经常听到的一个比方是:类就像模板,是一个抽象概念,对象就是用这个模板做出来的产品,是一个相对具象的概念。
面向对象的关键是我们要把现实世界中的一切,抽象为一个个对象,这很想生物中的物种分类:界门纲目科属种。比如:狗是一个类,那么你家养的宠物狗就是一个实例对象。类有属性和方法。属性是类的一些静态特征,是类的数据,对应狗的毛色、大小、性别等。方法是类的行为,是动态特征,通过类的方法,可以改变类的状态,对应狗跑步等行为。
面向对象 3 大基本特征继承
、封装
和多态
。这部分不在这篇文章讨论范围。
说这么多只是想说,Python 也是一门面向对象的语言,这些概念在 Python 中也完全适用。那么 Python 中一切皆对象
这句话又是说的什么呢?
答案是:Python 中,面向对象的"类"和"对象"都是通过对象实现的!
类在 Python 中也是对象。
3. Python 中对象的分类
Python 中一切皆对象,类也是对象,那么Python 中都有哪些对象呢?
Python 中的类有内置的类和自定义的类,内置的类如:int/dict/tuple/set;自定义的类:使用 class 定义的类。这些类,在 Python 中我们可以称之为 类型对象。
Python 中的类实例化之后得到的对象称为实例对象,比如:1024,{1, 2, 3},Dog() 等。
一张图总结如下:
代码演示如下:
In [1]: class Dog(): # 自定义类型对象
...: pass
...:
In [2]: int # 内置类型对象
Out[2]: int
In [3]: 1234 # 内置类型实例对象
Out[3]: 1234
In [4]: dog = Dog() # 自定义类型实例对象
In [5]: type(dog) # 可以通过 type() 函数查看一个对象的类型
Out[5]: __main__.Dog
In [6]: dog.__class__ # 也可以查看该对象的 __class__ 属性查看一个对象的类型
Out[6]: __main__.Dog
4. Python 对象模型
对象理论模型中,对象是通过类实例化得到的,这在Python 中也适用。通常我们可以用 type() 函数来查看一个对象的类型,或者通过 对象的 __class__
属性。我们也可以用 isinstance()
函数来判断一个实例对象是否由某个类型直接实例化而来。
在 Python 中,所有对象的类型都收敛于 type
。所以 type
也称为 元类
,它站在了 Python 中类型金字塔顶端。所有对象按照类型追根溯源,最后都是得到 type。所以 Python 中对象只有三种身份:实例对象、类型对象,元类。看看下面的代码:
In [10]: type(1234)
Out[10]: int
In [11]: type(int)
Out[11]: type
In [12]: type(type)
Out[12]: type
In [13]: type(dog)
Out[13]: __main__.Dog
In [14]: type(Dog)
Out[14]: type
In [15]: isinstance(1234, int)
Out[15]: True
In [16]: isinstance(dog, Dog)
Out[16]: True
In [17]: isinstance(dog, type) # 实例化对象 dog 不是由 type 直接实例化得到
Out[17]: False
In [18]: isinstance(Dog, type) # 自定义类由 type 实例化而来
Out[18]: True
In [19]: isinstance(int, type) # 内置类型由 type 实例化而来
Out[19]: True
In [20]: isinstance(type, type) # type 也是由 type 实例化而来!
Out[20]: True
type 的类型还是 type,type 也是由 type 实例化而来,它连自己都没有放过!它是怎么做到的?这里留待后面源码分析(先埋坑)。
还有一句话,在 Python 中所有对象的继承都收敛于 object
。object 站在了继承金字塔的顶端。可以通过 issubclass() 函数来判断一个类型是否是另一个类型的子类。注意,类型也是自己的子类!
In [21]: issubclass(int, object)
Out[21]: True
In [22]: issubclass(Dog, object)
Out[22]: True
In [23]: issubclass(type, object)
Out[23]: True
In [26]: issubclass(object, object)
Out[26]: True
In [28]: issubclass(int, int) # 注意,类型也是自己的子类!
Out[28]: True
In [29]: int.__base__
Out[29]: object
In [30]: Dog.__base__
Out[30]: object
Python 中是支持多继承的,但是一般不建议这么用,这是一个历史包袱。那么怎么查看一个对象都继承了哪些类呢?可以通过以下三个方法:
__base__
:如果继承多个类,只返回显式继承的第一个类,如果是隐式继承 object 则返回 object。__bases__
:以元组的形式返回所有显示继承的类,如果没有显式继承,则返回 object 元组。__mro__
:mro 是 method resolution order,表示方法查找顺序,会从自身出发,追溯到最顶层的类,因此返回 自身,继承的基类,基类继承的基类,直到 object。
In [31]: class A:
...: pass
...:
In [32]: class B:
...: pass
...:
In [33]: class C(A, B):
...: pass
...:
In [34]: A.__base__
Out[34]: object
In [35]: B.__base__
Out[35]: object
In [36]: C.__base__
Out[36]: __main__.A
In [37]: C.__bases__
Out[37]: (__main__.A, __main__.B)
In [38]: C.__mro__
Out[38]: (__main__.C, __main__.A, __main__.B, object)
In [39]: print(object.__base__)
None
通过上面的代码,很好的解释了上面几句话,同时我们发现,object 的所有对象的基类,但是不像 type,类型链上,type 也是有类型的,那就是 type。但是继承链上,object 没有继承 objet,而是 None,为什么呢?因为 Python 查找属性或者方法时,会追溯继承链,如果自身没有,就会按照 mro 顺序去基类查找,所以继承链一定要有个终点,不然就是死循环了。
最后用一张图总结 Python 中的对象模型: