2.2 Python对象和引用
2.2.1 Python对象概述
计算机程序通常用于处理各种类型的数据(即对象),不同的数据属于不同的数据类型,支持不同的运算操作。
在Python语言中,数据表示为对象。对象本质上是一个内存块,拥有特定的值,支持特定类型的运算操作。
在Python 3中,一切皆为对象。Python语言中的每个对象由标识(identity)、类型(type)和值(value)标识。
(1)标识用于唯一地标识一个对象,通常对应对象在计算机内存中的位置。使用内置函数id(obj1)可以返回对象obj1的标识。
(2)类型用于表示对象所属的数据类型(类),数据类型用于限定对象的取值范围以及允许执行的处理操作。使用内置函数type(obj1)可以返回对象obj1所属的数据类型。
(3)值用于表示对象的数据类型的值。使用内置函数print(obj1)可以返回对象obj1的值。
通过内置的type()函数可以判断一个对象的类型。通过内置的id()函数可以获取一个对象唯一的id标识(CPython的实现为内存存放位置)。
【例2.2】 使用内置函数type()、id()和print()查看对象。
字面量123创建一个实例对象,其id标识为140706558370656,类型为int类型,值为123。
在Python 3中函数和类等也是对象,也具有相应的类型和id。
【例2.3】 查看Python的内置函数对象。
2.2.2 使用字面量创建实例对象
对于内置对象,Python通常提供使用字面量直接创建实例对象的语法。
Python的数据类型定义了一个值的集合,在Python代码中使用字面量表示某个数据类型的值。例如,12、101等表示int数据类型的值;0.1 7、3.14等表示float数据类型的值;True和False表示bool数据类型的值;'Hello,World'、'张三'等表示str数据类型的值。
字面量在Python语句中解释为表达式,Python基于字面量创建相应的数据类型的对象。
【例2.4】 使用字面量创建实例对象。
Python使用字面量123和"abc"分别创建一个int型对象和一个str型对象。
2.2.3 使用类对象创建实例对象
通过直接调用类对象可以创建实例对象,其语法格式如下。
【例2.5】 使用类对象创建实例对象。
Python使用int(12)创建一个整数数据类型的实例对象;使用complex(1,2)创建一个复数类型的实例对象。
另外,表达式的运算结果也可以创建新的对象;Python语句def会创建函数对象;class语句会创建类对象,详细阐述请参见本书的后续章节。
2.2.4 数据类型
在Python语言中,所有对象都有一个数据类型。Python数据类型的定义为一个值的集合以及在这个值集上的一组运算操作。
例如整数数据类型(int),其值的集合为所有的整数,支持的运算操作包括+(加法)、-(减法)、*(乘法)、//(整除)等,88、1024等都是整数类型数据。
每个对象存储一个值,例如,int类型的对象可以存储值1234、99或1333。不同的对象可以存储同一个值,例如,一个str类型的对象可以存储值'hello',另一个str类型的对象也可以存储值'hello'。在一个对象上可执行且只允许执行其对应数据类型定义的操作,例如,两个int对象可执行乘法运算,但两个str对象不允许执行乘法运算。
Python数据类型包括内置数据类型和自定义数据类型。Python语言提供了丰富的内置数据类型,用于有效地处理各种类型的数据。本书后续章节将展开内置数据类型和自定义数据类型的阐述。
2.2.5 变量和对象的引用
Python对象是位于计算机内存中的一个内存数据块。为了引用对象,用户必须通过赋值语句把对象赋值给变量(也称之为把对象绑定到变量)。指向对象的引用即变量。
【例2.6】 使用赋值语句把对象绑定到变量。
Python使用字面量表达式1、2和表达式a+b创建3个整型对象,并使用赋值语句把3个对象分别绑定到变量a、b和c。
字面量用于创建值为字面量的对象,即某个数据类型的实例对象;表达式使用运算符实现多个操作数(对象)的运算操作,并返回结果对象。用户可以把对象通过赋值语句赋值给一个变量,即把对象绑定到一个变量,注意变量名必须为有效的标识符。
在Python 3中,作为对象的函数和类等也可以通过变量引用,但这样的引用一般意义不大,建议直接使用函数/类,以提高程序的可读性。例如:
2.2.6 Python是动态类型语言
Python是动态类型语言,即变量不需要显式声明数据类型。根据变量的赋值,Python解释器自动确定其数据类型。
事实上,变量仅用于指向某个类型对象,因此变量可以不限定类型,即可以指向任何类型的对象。
通过标识符和赋值运算符(=)可以指定某个变量指向某个对象,即引用该对象。多个变量可以引用同一个对象,一个变量也可以改变指向其他的对象。
【例2.7】 变量的动态类型示例。
123为类int的对象实例,其id为140706558370656;a=123,即变量a指向(引用)对象实例123,故其id也为140706558370656;b=123,即变量b也指向(引用)对象实例123,故其id也为140706558370656;c=a,变量c和变量a一样,指向(引用)对象实例123,其id同样为140706558370656。a='abc',变量a指向(引用)对象实例'abc',其id为2529314137232。
2.2.7 Python是强类型语言
Python是一种强类型语言,每个变量指向的对象均属于某个数据类型,即只支持该类型允许的运算操作。
【例2.8】 变量的强数据类型示例。
2.2.8 对象内存示意图
Python程序运行时会在内存中创建各种对象(位于堆内存中),通过赋值语句可以将对象绑定到变量(位于栈内存中),从而通过变量引用对象进行各种操作。
多个变量可以引用同一个对象。如果一个对象不再被任何有效作用域中的变量引用,则会通过自动垃圾回收机制回收该对象占用的内存。
为了更好地理解Python对象和变量的作用机制,本书采用对象内存示意图进行演示。
【例2.9】 变量增量运算示例以及相应的对象内存示意图。
第1条语句,创建一个值为100的int对象,并绑定到变量i;第2条语句,先计算表达式i+1的值,然后创建一个值为101的int对象,并绑定到变量i。
执行各条语句后,其对象内存示意图如图2-1所示。
注意:在执行完第2条语句后,内存中存在3个int对象,即100、1和101,变量i引用对象101,其他两个对象没有被任何变量引用,将被自动垃圾回收器回收。
【例2.10】 交换两个变量的示例以及相应的对象内存示意图。
在执行各条语句后,其对象内存示意图如图2-2所示。
图2-1 变量增量运算示例的对象内存示意图
图2-2 两个变量交换示例的对象内存示意图
2.2.9 对象的值比较和引用判别
通过==运算符可以判断两个变量指向的对象的值是否相同;通过is运算符可以判断两个变量是否指向同一对象。
【例2.11】 对象的值比较(==)和引用判别(is)示例。
2.2.10 不可变对象和可变对象
Python 3对象可以分为不可变对象(immutable)和可变对象(mutable)。不可变对象一旦创建,其值就不能被修改;可变对象的值可以被修改。Python对象的可变性取决于其数据类型的设计,即是否允许改变其值。
Python中的大部分对象都是不可变对象,例如int、str、complex等。变量是指向某个对象的引用,多个变量可以指向同一个对象。给变量重新赋值,并不改变原始对象的值,只是创建一个新对象,并指向该变量。
【例2.12】 不可变对象示例。
对象本身的值可以改变的对象称为可变对象(例如list、dict等)。
【例2.13】 可变对象示例。