第5章

数 据 类 型





在声明变量时会用到数据类型,前面已经用到过一些数据类型,例如整数和字符串等。在Python中所有的数据类型都是类,每一个变量都是类的“实例”。没有基本数据类型的概念,所以整数、浮点和字符串也都是类。
Python有6种标准数据类型: 数字、字符串、列表、元组、集合和字典,其中列表、元组、集合和字典可以保存多项数据,它们每一个都是一种数据结构,本书中把它们统称为“数据结构”类型。
本章先介绍数字和字符串,列表、元组、集合和字典数据类型将在后续章节详细介绍。
5.1数字类型
Python数字类型有4种: 整数类型、浮点类型、复数类型和布尔类型。注意: 布尔类型也是数字类型,是整数类型的一种。
5.1.1整数类型
Python整数类型为int。整数类型的范围可以很大,可以表示很大的整数,只受所在计算机硬件的限制。



提示
Python3不再区分整数和长整数,所有需要的整数都可以是长整数。




默认情况下一个整数值表示的是十进制数,如16表示的是十进制整数。其他进制整数表示方式如下: 
(1) 二进制数: 以0b或0B为前缀。注意0是阿拉伯数字,不是英文字母o。
(2) 八进制数: 以0o或0O为前缀。第1个字符是阿拉伯数字0,第2个字符是英文字母o或O。
(3) 十六进制数: 以0x或0X为前缀。注意0是阿拉伯数字。
整数值28、0b11100、0B11100、0o34、0O34、0x1C和0X1C都表示同一个数字。在Python Shell输出结果如下: 

>>> 28

28

>>> 0b11100

28

>>> 0O34

28

>>> 0o34

28

>>> 0x1C

28

>>> 0X1C

28

5.1.2浮点类型
浮点类型主要用来储存小数数值。Python浮点类型为float,Python只支持双精度浮点类型,且与本机相关。
浮点类型可以用小数表示,也可以用科学计数法表示,科学计数法中用大写或小写的e表示10的指数,如e2表示102。
在Python Shell中运行示例如下: 

>>> 1.0

1.0

>>> 0.0

0.0

>>> 3.36e2

336.0

>>> 1.56e-2

0.0156


其中3.36e2表示的是3.36×102,1.56e2表示的是1.56×10-2。
5.1.3复数类型
复数在数学中是非常重要的概念,无论在理论物理学,还是在电气工程实践中都经常使用。但是很多计算机语言都不支持复数,而Python是支持复数的,这使得Python能够很好地用来进行科学计算。
Python中复数类型为complex,如1+2j表示实部为1、虚部为2的复数。在Python Shell中运行示例如下: 

>>> 1+2j

(1+2j)

>>> (1+2j) + (1+2j)

(2+4j)

上述代码实现了两个复数(1+2j)的相加。
5.1.4布尔类型
Python中布尔类型为bool。bool是int的子类,它只有两个值: True和False。



注意
任何类型数据都可以通过bool()函数转换为布尔值,那些被认为“没有的”“空的”值将转换为False,反之转换为True。如None(空对象)、False、0、0.0、0j(复数)、"(空字符串)、[](空列表)、()(空元组)和{}(空字典)等将转换为False,其他将转换为True。




示例如下: 

>>> bool(0)

False

>>> bool(2)		

True

>>> bool(1)

True

>>> bool('')

False

>>> bool('  ')

True

>>> bool([])

False

>>> bool({})

False

上述代码中bool(2)和bool(1)表达式输出的是True,说明2和1都能转换为True,在整数中只有0是转换为False的。
5.2数字类型相互转换
学习了前面的数据类型后,大家会思考一个问题,数据类型之间是否可以转换呢?Python通过一些函数可以实现不同数据类型之间的转换,如数字类型之间及整数与字符串之间的转换。本节先讨论数字类型的互相转换。
除复数外,其他3种数据类型(整数类型、浮点类型和布尔类型)都可以互相转换,转换分为隐式类型转换和显式类型转换。
5.2.1隐式类型转换
多个类型数据之间可以进行数学计算。参与计算的数据类型不同时,将发生隐式类型转换。计算过程中隐式类型转换规则如表51所示。


表51隐式类型转换规则



操作数1类型操作数2类型转换后的类型
布尔整数整数
布尔、整数浮点浮点

布尔类型数值可以隐式转换为整数类型,布尔类型数值True转换为整数1,布尔类型数值False转换为整数0。在Python Shell中运行示例如下: 

>>> a = 1 + True

>>> print(a)

2

>>> a = 1.0 + 1

>>> type(a)①

<class 'float'>

>>> print(a)

2.0

>>> a = 1.0 + True

>>> print(a)

2.0

>>> a = 1.0 + 1 + False

>>> print(a)

2.0

另外,上述代码第①行使用了type()函数,该函数可以返回传入数据的类型,<class'float'>代表浮点类型。
5.2.2显式类型转换
在不能进行隐式转换情况下,可以使用转换函数进行显式转换。除复数外,3种数据类型(整数类型、浮点类型和布尔类型)都有各自的转换函数,分别是int()、float()和bool()函数。bool()函数在5.1.4节已经介绍过了,这里不再赘述。
int()函数可以将布尔类型、浮点类型和字符串转换为整数。布尔类型数值True使用int()函数返回1,False使用int()函数返回0; 浮点类型数值使用int()函数会截掉小数部分。int()函数转换字符串将在5.3节介绍。
float()函数可以将布尔类型、整数类型和字符串转换为浮点类型。布尔类型数值True使用float()函数返回1.0,False使用float()函数返回0.0; 整数类型数值使用float()函数会加上小数部分“.0”。float()函数转换字符串将在5.3节介绍。
在Python Shell中运行示例如下: 

>>> int(False)

0

>>> int(True)

1

>>> int(19.6)

19

>>> float(5)

5.0

>>> float(False)

0.0

>>> float(True)

1.0

5.3字符串类型
由字符组成的一串字符序列称为字符串。字符串是有顺序的,从左到右,索引从0开始依次递增。Python中字符串类型是str。
5.3.1字符串表示方式
Python中字符串的表示方式有如下3种。
1) 普通字符串
普通字符串: 采用单引号“'”或双引号“"”包裹起来的字符串。
很多程序员习惯使用单引号“'”表示字符串。下面示例表示的都是Hello World字符串。

'Hello World'

"Hello World"

'\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064'	①

"\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064"	②

Python中的字符采用Unicode编码,所以字符串可以包含中文等亚洲字符。代码第①行和第②行的字符串用Unicode编码表示的Hello World字符串,可通过print函数将其输出到控制台,将显示为Hello World字符串。在Python Shell中运行示例如下: 

>>> s = 'Hello World'

>>> print(s)

Hello World

>>> s = "Hello World"

>>> print(s)

Hello World

>>> s = '\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064'

>>> print(s)

Hello World

>>> s = "\u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064"

>>> print(s)

Hello World

如果字符串中包含一些特殊的字符,如换行符、制表符等,在普通字符串中则需要转义,在前面加上反斜杠“\”,称为字符转义。表52所示是常用的转义符。


表52常用的转义符



字 符 表 示Unicode编码说明

\t\u0009水平制表符
\n\u000a换行
\r\u000d回车
\"\u0022双引号
\'\u0027单引号
\\\u005c反斜线

在Python Shell中运行示例如下: 

>>> s = 'Hello\n World'

>>> print(s)

Hello

 World

>>> s = 'Hello\t World'

>>> print(s)

Hello	 World

>>> s = 'Hello\' World'

>>> print(s)

Hello' World

>>> s = "Hello' World"	①

>>> print(s)

Hello' World

>>> s = 'Hello" World'		②

>>> print(s)

Hello" World

>>> s = 'Hello\\ World'	③

>>> print(s)

Hello\ World

>>> s = 'Hello\u005c World'	④

>>> print(s)

Hello\ World


字符串中的单引号“'”和双引号“"”也可以不用转义符。在包含单引号的字符串中应使用双引号包裹字符串,见代码第①行; 在包含双引号的字符串中应使用单引号包裹字符串,见代码第②行。另外,可以使用Unicode编码替代需要转义的特殊字符,代码第④行与代码第③行是等价的。
2) 原始字符串
原始字符串(raw string): 在普通字符串前加r,字符串中的特殊字符不需要转义,按照字符串的本来面目呈现。
原始字符串可以直接按照字符串的字面意思来使用,没有转义字符。在Python Shell中运行示例代码如下: 

>>> s = 'Hello\tWorld'  ①

>>> print(s)

Hello	World

>>> s = r'Hello\tWorld'  ②

>>> print(s)

Hello\tWorld

代码第①行是普通字符串,代码第②行是原始字符串,它们的区别只是在字符串前面加字母r。从输出结果可见,原始字符串中的\t没有被当成制表符使用。
3) 长字符串
长字符串: 字符串中包含了换行缩进等排版字符,可以使用三重单引号“'''”或三重双引号“"""”包裹起来。
在Python Shell中运行示例代码如下: 

>>> s  ='''Hello

 World'''

>>> print(s)

Hello

 World

>>> s = """ Hello \t			①

World"""

>>> print(s)

 Hello 	

World

长字符串中如果包含特殊字符也需要转义,见代码第①行。
5.3.2字符串格式化
在实际编程过程中,经常遇到将其他类型变量与字符串拼接到一起并进行格式化输出的情况,如计算的金额需要保留小数点后4位,数字需要右对齐等,这些都需要格式化。
在字符串格式化时可以使用字符串的format()方法及占位符。在Python Shell中运行示例如下: 

>>> name = 'Mary'

>>> age = 18

>>> s = '她的年龄是{0}岁。'.format(age)		①

>>> print(s)

她的年龄是18岁。

>>> s = '{0}年龄是{1}岁。'.format(name, age)	②

>>> print(s)

Mary年龄是18岁。

>>> s = '{1}年龄是{0}岁。'.format(age, name)	③

>>> print(s)

Mary年龄是18岁。

>>> s = '{n}年龄是{a}岁。'.format(n=name,  a=age)	④

>>> print(s)

Mary年龄是18岁。

字符串中可以有占位符({}表示的内容),配合format()方法使用,将用format()方法中的参数替换占位符内容。占位符可以用参数索引表示,见代码第①行、第②行和第③行,代码中0表示第1个参数,1表示第2个参数,以此类推。占位符也可以使用参数名表示占位符,见代码第④行,n和a都是参数名。
占位符中还可以有格式化控制符,对字符串的格式进行更加精准控制。不同的数据类型在格式化时需要不同的控制符,如表53所示。


表53字符串格式化控制符



控制符说明
s字符串格式化
d十进制整数
f、F十进制浮点类型数据
g、G十进制整数或浮点类型数据
e、E科学计算法表示浮点类型数据
o八进制整数,符号是小写英文字母o
x、X十六进制整数

格式控制符位于占位符索引或占位符名字的后面,之间用冒号分隔,如{1:d}表示索引为1的占位符格式参数是十进制整数。在Python Shell中运行示例如下: 

>>> name = 'Mary'

>>> age = 18

>>> money = 1234.5678

>>> "{0}年龄是{1:d}岁。".format(name, age)	①		

'Mary年龄是18岁。'

>>> "{1}年龄是{0:5d}岁。".format(age, name)	②

'Mary年龄是18岁。'

>>> "{0}今天收入是{1:f}元。".format(name, money)		③

'Mary今天收入是1234.567800元。'

>>> "{0}今天收入是{1:.2f}元。".format(name, money)		④

'Mary今天收入是1234.57元。'

>>> "{0}今天收入是{1:10.2f}元。".format(name, money)	⑤

'Mary今天收入是   1234.57元。'

>>> "{0}今天收入是{1:g}元。".format(name, money)		

'Mary今天收入是1234.57元。'

>>> "{0}今天收入是{1:G}元。".format(name, money)		

'Mary今天收入是1234.57元。'

>>> "{0}今天收入是{1:e}元。".format(name, money)		

'Mary今天收入是1.234568e+03元。'

>>> "{0}今天收入是{1:E}元。".format(name, money)		

'Mary今天收入是1.234568E+03元。'

>>> '十进制数{0:d}的八进制表示为{0:o},十六进制表示为{0:x}'.format(28)	

'十进制数28的八进制表示为34,十六进制表示为1c'


上述代码第①行中{1:d}是格式化十进制整数,代码第②行中{0:5d}指定输出长度为5的字符串,不足时用空格补齐。代码第③行中{1:f}是格式化十进制浮点数,从输出的结果可见,小数部分太长了。如果想控制小数部分可以使用代码第④行的{1:.2f}占位符,其中2表示保留小数两位(四舍五入)。如果想设置长度可以使用代码第⑤行的{1:10.2f}占位符,其中10表示总长度,包括小数点和小数部分,不足时用空格补位。
5.3.3字符串查找
在给定的字符串中查找子字符串是比较常见的操作。字符串类(str)中提供了find和rfind方法用于查找子字符串,返回值是查找到的子字符串所在位置,未找到则返回-1。下面具体说明find和rfind方法。
(1) str.find(sub[,start[,end]]): 在索引start到end查找子字符串sub,找到则返回最左端位置的索引,未找到则返回-1。start是开始索引,end是结束索引,这两个参数都可以省略,省略start说明查找从字符串头开始; 省略end说明查找到字符串尾结束; 全部省略即查找全部字符串。
(2) str.rfind(sub[,start[,end]]): 与find方法类似,区别是如果找到则返回最右端位置的索引。如果在查找的范围内只找到一处子字符串,则find和rfind方法返回值相同。



提示
在Python文档中[]表示可以省略部分,find和rfind方法参数[,start[,end]]表示start和end都可以省略。




在Python Shell中运行示例代码如下: 

>>> source_str = "There is a string accessing example."

>>> len(source_str)				①

36

>>> source_str[16]				②

'g'

>>> source_str.find('r')			

3

>>> source_str.rfind('r')

13

>>> source_str.find('ing')

14

>>> source_str.rfind('ing')

24

>>> source_str.find('e', 15)

21

>>> source_str.rfind('e', 15)

34

>>> source_str.find('ing', 5)

14

>>> source_str.rfind('ing', 5)

24

>>> source_str.find('ing', 18, 28)

24

>>> source_str.rfind('ingg', 5)

-1

上述代码第①行len(source_str)返回字符串长度。注意len是函数,不是字符串的一个方法,它的参数是字符串。代码第②行source_str[16]访问字符串中索引16的字符。
上述字符串查找方法比较类似,这里重点解释一下source_str.find('ing',5)和source_str.rfind('ing',5)表达式。从图51可见,ing字符串出现过两次,索引分别是14和24。source_str.nd('ing',5)返回最左端索引14,返回值为14; source_str.rnd('ing',5)返回最右端索引24。



图51source_str字符串索引





提示
函数与方法的区别是,方法是定义在类中的函数,在类的外部调用时需要通过类或对象调用,如上述代码中的source_str.find('r')就是调用字符串对象source_str的find方法,find方法是在str类中定义的; 而通常的函数也称为顶层函数,不是类中定义的,它们不属于任何一个类,调用时可以直接使用,如上述代码中的len(source_str)就调用了len函数,只不过它的参数是字符串对象source_str。




5.3.4字符串与数字相互转换
在实际编程过程中,经常用到字符串与数字相互转换。下面从两方面介绍字符串与数字相互转换。
1) 字符串转换为数字
字符串转换为数字可以使用int()和float()函数实现。5.2.2节介绍了这两个函数实现数字类型之间的转换,事实上这两个函数也可以接收字符串参数,如果字符串能成功转换为数字,则返回数字,否则将引发异常。
在Python Shell中运行示例代码如下: 

>>> int('9')

9

>>> int('9.6')

Traceback (most recent call last):

File "<pyshell#2>", line 1, in <module>

int('9.6')

ValueError: invalid literal for int() with base 10: '9.6'

>>> float('9.6')

9.6

>>> int('AB')

Traceback (most recent call last):

File "<pyshell#4>", line 1, in <module>

int('AB')

ValueError: invalid literal for int() with base 10: 'AB'

>>>

默认情况下int()函数都将字符串参数当成十进制数字进行转换,所以函数int('AB')将转换失败。int()函数也可以指定基数(进制),在Python Shell中运行示例如下: 

>>> int('AB', 16)

171


2) 数字转换为字符串
数字转换为字符串有很多种方法,5.3.2节介绍的字符串格式化即可将数字转换为字符串。另外,Python中还可以使用str()函数将任何类型的数字转换为字符串。在Python Shell中运行示例代码如下: 

>>> str(3.24)

'3.24'

>>> str(True)

'True'

>>> str([])

'[]'

>>> str([1,2,3])

'[1, 2, 3]'

>>> str(34)

'34'

从上述代码可以看到str()函数很强大,可以转换任意类型的数字。但缺点是不能格式化,格式化字符串需要使用format函数。在Python Shell中运行示例代码如下: 

>>> '{0:.2f}'.format(3.24)

'3.24'

>>> '{:.1f}'.format(3.24)

'3.2'

>>> '{:10.1f}'.format(3.24)

'       3.2'




提示
在格式化字符串时,如果只有一个参数,占位符索引可以省略。




5.4本章小结
本章主要介绍了Python中的数据类型,读者需要重点掌握数字类型与字符串类型,熟悉数字类型的互相转换,以及数字类型与字符串之间的转换。
5.5同步练习
1. 在Python中字符串的表示方式是()。

A. 采用单引号(')包裹起来B. 采用双引号(")包裹起来
C.  采用三重单引号(''')包裹起来D. 以上都可以
2. 下列表示数字正确的是()。
A. 29B. 0X1CC. 0x1AD. 1.96e2
3. 判断对错。
Python中布尔类型只有两个值: True和False。()
4. 判断对错。
bool()函数可以将None、0、0.0、0j(复数)、''(空字符串)、[](空列表)、()(空元组)和{}(空字典)这些数值转换为False。()