*注:该系列文章主要是对Python深入的学习的记录。

一切皆对象

Python 是一门面向对象语言。在Python的世界里,一切皆对象。

在面向对象的编程语言中,基本都存在 类型(如int型)以及对象。在Python中,类型也是一种对象(整数型是一个对象,字符串类型也是一个对象,class关键字定义的类也是一个对象)。Python的类型也可称为类型对象。

>>> int
<class 'int'>

这里的整数类型int便是一种类型对象。

而常规意义上的对象便是通过类型对象进行实例化操作所得,也叫着实例对象。

>>> int('100')
100

这里int()的过程便是实例化的过程,而得到100则属于实例对象。在Python中,一个整数是一个对象,一个字符串也是一个对象。

1.1 Python3 对象概述_变量名

Python不区别对待类型(包括基本数据类型或者是class定义的其他类)和对象,所有的类型在python内部均由对象实现,这便是Python一切皆对象的由来。

类型、对象体系

Python3提供了内置函数type(),可以返回对象的类型,而针对类型,则提供了__mro__属性,可以查看类型的继承关系。

>>> type(100)
<class 'int'>  # 实例对象100的类型是int
>>> type(int)
<class 'type'> # 类型对象int的类型是type
>>> type(type)
<class 'type'> # 类型对象type的类型是type自身
>>> int.__mro__
(<class 'int'>, <class 'object'>)  # 类型对象int的基类是object
>>> type.__mro__
(<class 'type'>, <class 'object'>) # 类型对象type的基类是object
>>> type(object)
<class 'type'>    # 类型对象object的类型是type

可以根据已掌握的知识点,比如object是所有类的基类,type是所有类型的元类等,结合上面的结果,归纳出类型和对象的体系。

1.1 Python3 对象概述_python_02

可以看到,所有类型的基类都是object,所有类型的类型(元类型)都是type,包括type自己。

对象存储

知道了类型与对象的体系,了解一下对象的存储。以整数1为例子。

>>> a = 1
>>> id(a)
9083104
>>> b = a
>>> id(b)
9083104
>>> id(1)
9083104

 根据上面的结果,可以看出,变量a、b、 整数1这三者的“地址”都是一样的。

根据其他的编程语言,这是比较奇怪的现象,比如在C中,变量a和变量b的内存空间应该是独立的,并且会将值进行拷贝,如下面的图例。

1.1 Python3 对象概述_变量名_03  1.1 Python3 对象概述_python_04

但在python中,一切皆对象,变量只是一个与对象关联的名字而已,这些变量名将在程序运行时存储于名字空间内,保存了指向实际对象的指针,进而与对象进行绑定。

1.1 Python3 对象概述_Python_051.1 Python3 对象概述_Python_06

变量的拷贝只是变量名所保存的指针的拷贝,并不拷贝指针背后的对象。当然,python也提供了拷贝对象的方式,比如copy.copy或者copy.deepcopy。

那么如果将变量的值进行修改,变量名所保存的指针是否会更改?

>>> a = 1
>>> id(a)
9083104
>>> a += 1
>>> id(a)
9083136

可以得出结论,如果整数变量的值被修改,该变量的地址也将被改变。

这里可能跟其他的编程语言差别也比较大,通常值被修改,只需要更改变量所指向的内存地址内的值,而不会更改变量所保存的指针。这里便涉及到python的对象设计---- 可变对象和不可变对象

在Python中,部分基本类型属于不可变类型,比如整数类型,其整数对象是不可变对象。修改整数对象时,python将以新数值创建一个新对象(这里存在优化手段,暂不涉及),变量名与新对象进行绑定;旧对象如无其他引用,将被释放。

1.1 Python3 对象概述_Python_07

而可变对象则是指创建后可以修改的对象,在python中,典型的可变对象便是 列表(list):

>>> a = [1, 2]
>>> id(a)
140441701802056
>>> a.append(3)
>>> id(a)
140441701802056

 根据结果可以看出,列表的值发生了改变,但变量存储的指针并没有改变。这与可变对象的实现有关,在python中,列表对象内部维护了一个动态数组,用以存储元素对象的指针。

1.1 Python3 对象概述_Python_08

如此,当修改列表时,只需要修改动态数组即可,比如添加一个元素3。

1.1 Python3 对象概述_编程语言_09