Python的核心数据类型
在Python程序中处理的每样东西都是一种对象。例如,在Python中进行文本模式匹配时,创建了模式对象,还有进行网络脚本编程时,使用了套接字对象。其他类型的对象往往都是通过导入或使用模块来建立的,而且它们都有各自的行为。
Python是动态类型的(它自动地跟踪你的类型而不是要求声明代码),但是它也是强类型语言(你只能对一个对象进行适合该类型的有效的操作)。
动态类型语言
在Python中,类型是在运行过程中自动决定的,而不是通过代码声明。这意味着没有必要事先声明变量。
变量和对象保存在内存中的不同部分。
变量名和对象,在运行a=3后。变量a变成对象3的一个引用。在内部,变量事实上是到对象内存空间(通过运行常量表达式3而创建)的一个指针
==与is
“==操作符”,测试两个被引用的对象是否有相同的值。这种方法往往在Python中用作相等的检查。“is操作符”,是在检查对象的同一性。如果两个变量名精确地指向同一个对象,它会返回True。实际上,is只是比较实现引用的指针。
注意常量引用同一个对象
数字
Python的核心对象集合包括常规的类型:整数(没有小数部分的数字)、浮点数(概括地讲,就是后边有小数部分的数字)以及更为少见的类型(有虚部的复数、固定精度的十进制数、带分子和分母的有理分数以及集合等)。
对于浮点数,最好将其作为str打印出来,除了表达式外,和Python一起分发的还有一些常用的数学模块,模块只不过是我们导入以供使用的一些额外工具包。
math模块包括更高级的数学工具,如函数,而random模块可以作为随机数字的生成器和随机选择器
表达式操作符
强制类型转换
可以通过手动调用内置函数来强制转换类型:
然而,通常是没有必要这样做的。因为Python在表达式中自动升级为更复杂的类型,其结果往往就是你所想要的
除法
在Python 3.0中,/现在总是执行真除法(无论任何类型都会保持小数部分)。不管操作数的类型,都返回包含任何余数的一个浮点结果。//执行Floor除法,它截除掉余数并且针对整数操作数返回一个整数,如果有任何一个操作数是浮点类型,则返回一个浮点数。
math库
内置函数pow和abs,分别计算幂和绝对值。这里有一些内置math模块(包含在C语言中math库中的绝大多数工具)的例子并有一些实际中的内置函数。
数学库
尽管Python的核心数字类型提供的功能对于大多数应用程序已经够用了,还是有大量的第三方开源扩展可以用来解决更加专门的需求。由于数字编程是Python的常用领域,你将会发现众多的高级工具。
例如,如果你需要做一些正式的数字计算,一个叫做NumPy(Numeric Python)的可选的Python扩展提供了高级的数字编程工具,例如矩阵数据类型、向量处理和高级的计算库。像Los Alamos和NASA这样的核心科学编程组织,使用带有NumPy的Python来实现此前用C++、FORTRAN、Matlab编写的任务。Python和NumPy的组合往往可以比作是一款免费的、更加灵活的Matlab,可以得到NumPy的性能以及Python语言及其库。
字符串
字符串是单个字符的字符串的序列,其他类型的序列还包括列表和元组。python和像C这样的语言不一样,没有单个字符的这种类型,取而代之的是可以使用一个字符的字符串。
作为序列,字符串支持假设其中各个元素包含位置顺序的操作。例如,如果我们有一个含有四个字符的字符串,我们通过内置的len函数验证其长度并通过索引操作得到其各个元素。
三重引号
Python有一种三重引号内的字符串常量格式,有时候称作块字符串,这是一种对编写多行文本数据来说很便捷的语法。这个形式以三重引号开始(单引号和双引号都可以),并紧跟任意行数的文本,并且以开始时的同样的三重引号结尾。嵌入在这个字符串文本中的单引号和双引号也会,但不是必须转义——直到Python看到和这个常量开始时同样的三重引号,这个字符串才会结束。
索引
在Python中,我们能够反向索引,从最后一个开始(正向索引是从左边开始计算,反向索引是从右边开始计算)。
值得注意的是,我们能够在方括号中使用任意表达式,而不仅仅是使用数字常量——只要Python需要一个值,我们可以使用一个常量、一个变量或任意表达式。Python的语法在这方面是完全通用的。
切片
除了简单地从位置进行索引,序列也支持一种所谓分片(slice)的操作,这是一种一步就能够提取整个分片(slice)的方法。例如:
在一个分片中,左边界默认为0,并且右边界默认为分片序列的长度。这引入了一些常用法的变体:
字符串运算
最后,作为一个序列,字符串也支持使用加号进行合并(将两个字符串合成为一个新的字符串),或者重复(通过再重复一次创建一个新的字符串):
字符串不可写(不可变)
注意:在之前的例子中,没有通过任何操作对原始的字符串进行改变。每个字符串都被定义为生成新的字符串作为其结果,因为字符串在Python中具有不可变性——在创建后不能就地改变。
例如,不能通过对其某一位置进行赋值而改变字符串,但是你总是可以通过建立一个新的字符串并以同一个变量名对其进行赋值。因为Python在运行过程中会清理旧的对象
上面的例子中,变量被赋予新的对象,相当于没有指针指向旧对象,最后会被GC
常用方法
字符串的find方法是一个基本的子字符串查找的操作(它将返回一个传入子字符串的偏移量,或者没有找到的情况下返回-1),而字符串的replace方法将会对全局进行搜索和替换。
其他的方法还能够实现通过分隔符将字符串拆分为子字符串(作为一种解析的简单形式),大小写变换,测试字符串的内容(数字、字母或其他),去掉字符串后的空格字符。
字符串还支持一个叫做格式化的高级替代操作,可以以一个表达式的形式(最初的)和一个字符串方法调用形式使用(通常在打日志的时候有用):
转义与单双引号
反斜线转义序列表示特殊的字符
Python允许字符串包括在单引号或双引号中(它们代表着相同的东西)。它也允许在三个引号(单引号或双引号)中包括多行字符串常量。当采用这种形式的时候,所有的行都合并在一起,并在每一行的末尾增加换行符。
正则匹配
通常使用re模块。这个模块包含了类似搜索、分割和替换等调用,但是因为使用模式去定义子字符串,可以更通用一些:
这个例子的目的是搜索子字符串,这个子字符串以"Hello,"开始,后面跟着零个或几个制表符或空格,接着有任意字符并将其保存至匹配的group中,最后以"world."结尾。如果找到了这样的子字符串,与模式中括号包含的部分匹配的子字符串的对应部分保存为组。例如,下面的模式取出了三个被斜线所分割的组:
列表
Python的列表对象是这个语言提供的最通用的序列。列表是一个任意类型的对象的位置相关的有序集合,它没有固定的大小。
由于列表是序列的一种,列表支持所有的我们对字符串所讨论过的序列操作。唯一的区别就是其结果往往是列表而不是字符串。例如,有一个有三个元素的列表:
我们能够对列表进行索引、切片等操作,就像对字符串所做的操作那样:
常用方法
为列表是可变的,大多数列表的方法都会就地改变列表对象,而不是创建一个新的列表。列表没有固定类型的约束,列表没有固定大小,也就是说能够按照需要增加或减小列表大小,来响应其特定的操作:
列表sort方法,默认按照升序对列表进行排序,而reverse对列表进行翻转
嵌套
Python核心数据类型的一个优秀的特性就是它们支持任意的嵌套。能够以任意的组合对其进行嵌套,并可以多个层次进行嵌套(例如,能够让一个列表包含一个字典,并在这个字典中包含另一个列表等)。这种特性的一个直接的应用就是实现矩阵,或者Python中的“多维数组”。一个嵌套列表的列表能够完成这个基本的操作:
这里,我们编写了一个包含3个其他列表的列表。其效果就是表现了一个3×3的数字矩阵。这样的结构可以通过多种方法获取元素。
列表解析
列表解析源自集合的概念。它是一种通过对序列中的每一项运行一个表达式来创建一个新列表的方法,每次一个,从左至右。列表解析是编写在方括号中的(提醒你在创建列表这个事实),并且由使用了同一个变量名的(这里是row)表达式和循环结构组成。可以看作是简写表达式的语法糖。
这个列表解析表达基本上就是它字面上所讲的:“把矩阵M的每个row中的row[1],放在一个新的列表中”。 实际应用中的列表解析可以更复杂:
字典
Python中的字典是完全不同的东西:它们不是序列,而是一种映射(mapping)。映射是一个其他对象的集合,但是它们是通过键而不是相对位置来存储的。字典是Python核心对象集合中的唯一的一种映射类型,也具有可变性——可以就地改变,并可以随需求增大或减小,就像列表那样。
作为常量编写时,字典编写在大括号中,并包含一系列的“键:值”对。
我们可以通过键对这个字典进行索引来读取或改变键所关联的值。字典的索引操作使用的是和序列相同的语法,但是在方括号中的元素是键,而不是相对位置。
创建字典的另一种方法
字典嵌套
下边的这个字典,一次将所有内容编写进一个常量,将可以记录更多的结构化信息。
键的排序:for循环
因为字典不是序列,它们并不包含任何可靠的从左至右的顺序。这意味着如果我们建立一个字典,并将它打印出来,它的键也许会以与我们输入时不同的顺序出现:
一个常用的解决办法就是通过字典的keys方法收集一个键的列表,使用列表的sort方法进行排序,然后使用Python的for循环逐个进行显示结果
另一个简单的方法是使用sorted函数
元组
元组对象(tuple,发音为"toople"或"tuhple")基本上就像一个不可以改变的列表。就像列表一样,元组是序列,但是它具有不可变性,和字符串类似。从语法上讲,它们编写在圆括号中而不是方括号中,它们支持任意类型、任意嵌套以及常见的序列操作:
元组还有两个专有的可调用方法,但它的专有方法不像列表所拥有的那么多:
元组的真正的不同之处就在于一旦创建后就不能再改变。也就是说,元组是不可变的序列,元组提供了一种完整性的约束。
集合
集合更像是一个无值的字典的键,有两种方法创建集合,使用set或直接定义({})。注意,在Python中{}仍然是一个字典。空的集合必须通过内置函数set来创建。
集合只能包含不可变的(即可散列的)对象类型。因此,列表和字典不能嵌入到集合中,但是,如果你需要存储复合值的话,元组是可以嵌入的。
布尔值
预定义的True和False对象实际上是定制后以逻辑结果显示的整数1和0,可以使用bool函数
文件
文件对象是Python代码对电脑上外部文件的主要接口。虽然文件是核心类型,但是它有些特殊:没有特定的常量语法创建文件。要创建一个文件对象,需调用内置的open函数以字符串的形式传递给它一个外部的文件名以及一个处理模式的字符串。例如,创建一个文本输出文件,可以传递其文件名以及'w'处理模式字符串以写数据:
这样就在当前文件夹下创建了一个文件,并向它写入文本(文件名可以是完整的路径,如果需要读取电脑上其他位置的文件)。为了读出刚才所写的内容,重新以'r'处理模式打开文件,读取输入(如果在调用时忽略模式的话,这将是默认的)。之后将文件的内容读至一个字符串,并显示它。对脚本而言,文件的内容总是字符串,无论文件包含的数据是什么类型:
如今读取一个文件的最佳方式就是根本不读它,文件提供了一个迭代器(iterator),它在for循环或其他环境中自动地一行一行地读取。
open函数能够实现在Python中编写的绝大多数文件处理。尽管这样,对于更高级的任务,Python还有额外的类文件工具:管道、先进先出队列(FIFO)、套接字、通过键访问文件、对象持久、基于描述符的文件、关系数据库和面向对象数据库接口等。例如,描述符文件(descriptor file)支持文件锁定和其他的底层工具,而套接字提供网络和进程间通信的接口。
内容来源
[1] [美] Lutz,M.Phthon学习手册(第4版).机械工业出版社,2011.