Python使用对象模型来存储数据。构造任何类型的值都是一个对象。尽管Python通常被当成一种“面向对象的编程语言”,但你完全能够写出不使用任何类和实例的实用脚本。不过Python的对象语法和架构鼓励我们使用这些特性,下面让我们仔细研究一下Python对象。
所有的Python对像都拥有三个特性:身份,类型和值。
身份:每一个对象都有一个唯一的身份标识自己,任何对象的身份可以使用内建函数id()来得到。这个值可以被认为是该对象的内存地址。你极少会用到这个值,也不用太关心它究竟是什么。
类型:对象的类型决定了该对象可以保存什么类型的值,可以进行什么样的操作,以及遵循什么样的规则。你可以用内建函数type()查看Python对象的类型。因为在Python中类型也是对象(还记得我们提到Python是面向对象的这句话吗?),所以type()返回的是对象而不是简单的字符串。
值:对象表示的数据项。
上面三个特性在对象创建的时候就被赋值,除了值之外,其他两个特性都是只读的。对于新式类型和类,对象的类型也是可以改变的,不过并不推荐初学者这样做。
如果对象支持更新操作,那么它的值就可以改变,否则它的值也是只读的。对象的值是否可以更改被称为对象的可改变性(mutability),我们会在后面的4.7小节中讨论这个问题。只要一个对象还没有被销毁,这些特性就一直存在。
Python有一系列的基本(内建)数据类型,必要时也可以创建自定义类型来满足你对应用程序的需求。绝大多数应用程序通常使用标准类型,对特定的数据存储则通过创建和实例化类来实现。
对象属性
某些Python对象有属性、值或相关联的可执行代码,比如方法(method)o Python用句点(.)标记法来访问属性。属性包括相应对象的名字等,在2.14小节中曾做过介绍。最常用的属性是函数和方法,不过有一些Python类型也有数据属性。含有数据属性的对象包括(但不限于):类、类实例、模块、复数和文件。
数字(分为几个子类型,其中有三个是整型)
Integer整型
Boolean布尔型
Long integer长整型
Floating point real number浮点型
Complex number复数型
String字符串
List列表
Tuple元组
Dictionary字典
标准类型也称作“基本数据类型“,因为这些类型是Python内建的基本数据类型。
类型
Null对象(None)
文件
集合/固定集合
函数/方法
模块
类
这些是当你做Python开发时可能会用到的一些数据类型。我们在这里讨论Type和None类型的使用
1. 类型对象和type类型对象
虽然看上去把类型本身也当成对象有点特别,我们还是要在这里提一提。你一定还记得,对象的一系列固有行为和特性(比如支持哪些运算,具有哪些方法)必须事先定义好。
从这个角度看,类型正是保存这些信息的最佳位置。描述一种类型所需要的信息不可能用一个字符串来搞定,所以类型不能是一个简单的字符串,这些信息不能也不应该和数据保存在一起,所以我们将类型定义成对象。
下面我们来正式介绍内建函数type()。通过调用type()函数你能够得到特定对象的类型信息。
type (42)
我们仔细研究一下这个例子,请注意看type函数有趣的返回值。我们得到一个简洁的输出结果
现在你该问自己了,那么类型对象的类型是什么?来,我们试验一下。
type(type(42))
没错,所有类型对象的类型都是type,它也是所有Python类型的根和所有Python标准类的默认元类(metadass)。你现在有点搞不明白,没关系,随着我们逐步深入地学习类和类型,你就会慢慢理解。
随着Python 2.2中类型和类的统一,类型对象在面向对象编程和日常对象使用中扮演着更加重要的角色。从现在起,类就是类型,实例是对应类型的对象。
2.None——Python的 Null对象
Python有一个特殊的类型,被称为Null对象或者NoneType,它只有一个值,那就是None。它不支持任何运算也没有任何内建方法。如果非常熟悉C语言,就会知道和None类型最接近的C类型就是 void, None类型的值和C的NULL值非常相似(其他类似的对象和值包括Perl的undef和Java的void类型和null值)。
None没有什么有用的属性,它的布尔值总是False。
所有标准对象均可用于布尔测试,同类型的对象之间可以比较大小。每个对象天生具有布尔True或False值。空对象、值为零的任何数字或者Null对象None的布尔值都是False。
下列对象的布尔值是False。
None;
False (布尔类型);
所有的值为零的数;
0 (整型);
0.0 (浮点型);
0L (长整型);
0.0+0.0j (复数);
“”(空字符串);
[](空列表);
()(空元组);
{}(空字典)。
值不是上面列出来的任何值的对象的布尔值都是True,例如non-empty、non-zero等。用户创建的类实例如果定义了 nonzero(nonzero())或length(len())且值为0,那么它们的布尔值就是False。
代码
帧
跟踪记录
切片
省略
Xrange
我们在这里简要介绍一下这些内部类型,一般的程序员通常不会直接和这些对象打交道。
你如果对异常感到迷惑的话,可以告诉你它们是用类来实现的。在老版本的Python中,异常是用字符串来实现的。
1. 代码对象
代码对象是编译过的Python源代码片段,它是可执行对象。通过调用内建函数compile()可以得到代码对象。代码对象可以被exec命令或eval()内建函数来执行。
代码对象本身不包含任何执行环境信息,它是用户自定义函数的核心,在被执行时动态获得上下文。(事实上代码对象是函数的一个属性)一个函数除了有代码对象属性以外,还有一些其他函数必须的属性,包括函数名、文档字符串、默认参数、及全局命名空间等。
2. 帧对象
帧对象表示Python的执行栈帧。帧对象包含Python解释器在运行时所需要知道的所有信息。它的属性包括指向上一帧的链接,正在被执行的代码对象(参见上文),本地及全局名称空间字典及当前指令等。每次函数调用产生一个新的帧,每一个帧对象都会相应创建一个C栈帧。用到帧对象的一个地方是跟踪记录对象。
3. 跟踪记录对象
当你的代码出错时,Python就会引发一个异常。如果异常未被捕获和处理,解释器就会退出脚本运行,显示类似下面的诊断信息。
当异常发生时,一个包含针对异常的栈跟踪信息的跟踪记录对象被创建。如果一个异常有自己的处理程序,处理程序就可以访问这个跟踪记录对象。
4. 切片对象
当使用Python扩展的切片语法时,就会创建切片对象。扩展的切片语法允许对不同的索引切片操作,包括步进切片、多维切片和省略切片。多维切片语法是sequence[startl :endl,start2 : end2]
,或使用省略号,sequence[…,startl : end1 ]
。切片对象也可以由内建函数 slice()来生成。步进切片允许利用第3个切片元素进行步进切片,它的语法为sequence[起始索引:结束索引:步进值]
。Python很早就支持扩展步进切片语法了,但直到Python2.3以前都必须依靠C语言的API或Jython才能工作。
5. 省略对象
省略对象用于扩展切片语法中,起记号作用。这个对象在切片语法中表示省略号。类似Null对象 None,省略对象有一个唯一的名字Ellipsis,它的布尔值始终为True。
6. XRange对象
调用内建函数xrange()会生成一个Xrange对象,xrange()是内建函数range()的兄弟版本,用于需要节省内存使用或range()无法完成的超大数据集场合。在第8章你可以找到更多关于range()和xrange()的使用信息。
Python2.2统一了类型和类,所有的内建类型现在也都是类,在这基础之上,原来的所谓内建转换函数像int()、type()、 list()等,现在都成了工厂函数。也就是说虽然他们看上去有点像函数,实质上他们是类。当你调用它们时,实际上是生成了该类型的一个实例,就像工厂生产货物一样。
下面这些大家熟悉的工厂函数在之前的Python版里被称为内建函数。
int (), long (), float (), complex ()
str(), unicode (), basestring ()
list (), tuple()
type()
以前没有工厂函数的其他类型,现在也都有了工厂函数。除此之外,那些支持新式类的全新的数据类型,也添加了相应的工厂函数。下面列出了这些工厂函数。
dict ()
bool ()
set (), frozenset ()
object ()
classmethod ()
staticmethod ()
super ()
property ()
file ()
下面列出Python目前还不支持的数据类型:
char或 byte
Python没有char或byte类型来保存单一字符或8位整型。你可以使用长度为1的字符串表示字符或8位整型。
指针
Python替你管理内存,因此没有必要访问指针。在Python中你可以使用id()函数得到一个对象的身份号,这是最接近于指针的地址。因为你不能控制这个值,所以其实没有太大意义。其实在Python中,一切都是指针。
int vs short vs long
Python的普通整型相当于标准整型类型,不需要类似C语言中的int、short和long这三种整型类型。事实上Python的整型实现等同于C语言的长整型。由于Python的整型与长整型密切融合,用户几乎不需要担心什么。你仅需要使用一种类型,就是Python的整型。即便数值超出整型的表达范围,比如两个很大的数相乘,Python会自动的返回一个长整型给你而不会报错。
float vs double
C语言有单精度和双精度两种浮点类型。Python的浮点类型实际上是C语言的双精度浮点类型。 Python认为同时支持两种浮点类型的好处与支持两种浮点类型带来的开销不成比例,所以Python决定不支持单精度浮点型。对那些宁愿放弃更大的取值范围而需要更高精确度的用户来说,Python还有一种十进制浮点型类型Decimal,不过你必须导入decimal模块才可以使用它。浮点型总是不精确的。Decimals则拥有任意的精度。在处理金钱这类确定的值时,Decimal类型就很有用。在处理重量、长度或其他度量单位的场合,float足够用了。