第3章 Python的基本数据类型
本章摘要
3-1 type( )函数
3-2 数值数据类型
3-3 布尔值数据类型
3-4 字符串数据类型
3-5 字符串与字符
3-6 bytes数据
3-7 专题——地球到月球时间计算/计算坐标轴两点之间的距离
Python的基本数据类型有下列几种。
(1)数值数据类型(numeric type):常见的数值数据又可分成整数(int)、浮点数(float)、复数(complex number)(不常用所以不在本书讨论范围)。
(2)布尔值(Boolean)数据类型:也可归为数值数据类型。
(3)文字序列类型(text sequence type):也就是字符串(string)数据类型。
(4)字符组(bytes,有的书称字节)数据类型:这是二进制的数据类型,长度是8位。
(5)序列类型(sequence type):list(第6章说明)、tuple(第8章说明)。
(6)对映类型(mapping type):dict(第9章说明)。
(7)集合类型(set type):集合set(第10章说明)、冻结集合frozenset。
3-1 type( )函数
在正式介绍Python的数据类型前,笔者想介绍一下type( )函数,这个函数可以列出变量的数据类型类别。这个函数在读者未来进入Python实战时非常重要,因为变量在使用前不需要声明,同时在程序设计过程中变量的数据类型会改变,我们常常需要使用此函数判断目前的变量数据类型。或是在进阶Python应用中,会调用一些方法(method),这些方法会返回一些数据,可以使用type( )获得所返回的数据类型。
程序实例ch3_1.py:列出数值变量的数据类型。
执行结果
从上述执行结果可以看到,变量x的内容是10,数据类型是整数(int)。变量y的内容是3.33…3,数据类型是浮点数(float)。下一节会说明为何是这样。
3-2 数值数据类型
3-2-1 整数int
整数的英文是integer,在计算机程序语言中一般用int表示。如果读者学过其他计算机语言,在介绍整数时一定会告诉你,该计算机语言使用了多少空间存储整数,所以设计程序时整数的大小必须是在某一区间, 否则会有溢位(overflow)造成数据不正确。例如,如果存储整数的空间是32位,则整数大小为-2 147 483 648~2 147 483 647。在Python 2.x版时代,整数被限制在32位,另外还有长整数long,空间大小是64位,所以可以存储的数值更大,达到-9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807。在Python 3中已经将整数可以存储空间大小的限制取消了,所以没有long了,也就是说int可以是任意大小的数值。
英文googol是指自然数10100,计算机是用1e100显示,这是1938年美国数学家爱德华·卡斯纳(Edward Kasner) 9岁的侄子米尔顿·西罗蒂(Milton Sirotta)所创造的。下列是笔者尝试使用整数int显示此googol值。
3-2-2 浮点数
浮点数的英文是float,既然整数大小没有限制,浮点数大小当然也没有限制。在Python语言中,带有小数点的数字称为浮点数。例如:
x = 10.3
表示x是浮点数。
3-2-3 基本数值数据的使用
Python在声明变量时可以不用设置这个变量的数据类型,未来如果这个变量内容是放整数,这个变量就是整数(int)数据类型,如果这个变量内容是放浮点数,这个变量就是浮点数数据类型。整数与浮点数最大的区别是,整数不含小数点,浮点数含小数点。
程序实例ch3_2.py:测试浮点数。
执行结果
在程序实例ch3_1.py中,x变量的值是“10”,列出x变量是整数变量,在这个实例中,x变量的值是“10.0”,列出x变量是浮点数变量。
3-2-4 整数与浮点数的运算
Python程序设计时不相同的数据类型也可以执行运算,程序设计时常常会发生整数与浮点数之间的数据运算,Python具有简单的自动转换能力,在计算时会将整数转换为浮点数再执行运算。
程序实例ch3_3.py:不同数据类型的运算。
执行结果
上述变量y,由于是整数与浮点数的加法,所以结果是浮点数。此外,某一个变量如果是整数,但是如果最后所存储的值是浮点数,Python也会将此变量转成浮点数。
程序实例ch3_4.py:整数转换成浮点数的应用。
执行结果
原先变量x所存储的值是整数,所以列出的是整数。后来存储了浮点数,所以列出的是浮点数。
3-2-5 二进制整数与函数bin( )
可以用二进制方式代表整数,Python中定义凡是以0b开头的数字,代表这是二进制的整数。
bin( )函数可以将一般整数数字转换为二进制。
程序实例ch3_5.py:将十进制数值与二进制数值互转的应用。
执行结果
3-2-6 八进制整数与函数oct( )
可以用八进制方式代表整数,Python中定义凡是以0o开头的数字,代表这是八进制的整数。
oct( )函数可以将一般数字转换为八进制。
程序实例ch3_6.py:将十进制数值与八进制数值互转的应用。
执行结果
3-2-7 十六进制整数与函数hex( )
可以用十六进制方式代表整数,Python中定义凡是以0x开头的数字,代表这是十六进制的整数。
hex( )函数可以将一般数字转换为十六进制。
程序实例ch3_7.py:将十进制数值与八进制数值互转的应用。
执行结果
3-2-8 强制数据类型的转换
有时候设计程序时,可以自行强制使用下列函数,转换变量的数据类型。
int( ):将数据类型强制转换为整数。
float( ):将数据类型强制转换为浮点数。
程序实例ch3_8.py:将浮点数强制转换为整数的运算。
执行结果
程序实例ch3_9.py:将整数强制转换为浮点数的运算。
执行结果
3-2-9 数值运算常用的函数
下列是数值运算时常用的函数。
abs( ):计算绝对值。
pow(x,y):返回x的y次方。
round( ):这是采用运算法则的Bankers Rounding概念,如果处理位数左边是奇数则使用四舍五入,如果处理位数左边是偶数则使用五舍六入,例如,round(1.5)=2,round(2.5)=2。
处理小数时,第2个参数代表取到小数第几位,1代表取到小数第1位。根据保留小数位的后两位,采用"50"舍去,"51"进位,例如,round(2.15,1)=2.1,round(2.25,1)=2.2,round(2.151,1)=2.2,round(2.251,1)=2.3。
程序实例ch3_10.py:abs( )、pow( )、round( )、round(x,n)函数的应用。
执行结果
需留意的是,使用上述abs( )、pow( )或round( )函数,尽管可以得到运算结果,但是原先变量的值是没有改变的。
3-2-10 科学记数法
科学记数的概念如下,将一个数字转换成下列数学式:
a×10n
a是浮点数,例如,123456可以表示为1.23456 ×105,以10为基底数我们用E或e表示,指数部分则转为一般数字,然后省略“×”符号,最后表达式如下:
1.23456E+5
或
1.23456e+5
如果是碰上小于1的数值,则E或e右边是负值“-”。例如,0.000123转成科学记数法,最后表达式如下:
1.23E-4
或
1.23e-4
下列是示范输出。
4-2-2节和4-2-3节会介绍将一般数值转成科学记数法输出的方式,以及格式化输出方式。
3-3 布尔值数据类型
Python的布尔值(Boolean)数据类型的值有两种,True(真)或False(伪)。它的数据类型代号是bool。布尔值一般应用在程序流程的控制中,特别是在条件表达式中,程序可以根据这个布尔值判断应该如何执行下一步工作。
程序实例ch3_11.py:列出布尔值True与布尔值False的数据类型。
执行结果
如果将布尔值数据类型强制转换成整数,如果原值是True,将得到1;如果原值是False,将得到0。
程序实例ch3_12.py:将布尔值强制转换为整数,同时列出转换的结果。
执行结果
在本章一开始说过,有时候也可以将布尔值当作数值数据,因为True会被视为1,False会被视为0,可以参考下列实例。
程序实例ch3_13.py:将布尔值与整数值相加,并观察最后变量数据类型,可以发现,最后的变量数据类型是整数值。
执行结果
此外,在程序设计中False值不一定是要经过条件判断是False,才可以得到False,下列情况也会被视为False。
布尔值False 整数0 浮点数0.0 空字符串 '' 空列表 [ ] 空元组 ( ) 空字典 { } 空集合 set( ) None
至于其他的都会被视为True。
3-4 字符串数据类型
字符串(string)数据是指两个单引号(‘)之间或是两个双引号(“)之间任意个数字元符号的数据,它的数据类型代号是str。在英文字符串的使用中常会发生某字中间有单引号的情况,其实这是文字的一部分,如下所示:
This is James's ball
如果用单引号去处理上述字符串将产生错误,如下所示:
碰到这种情况,可以用双引号解决,如下所示:
程序实例ch3_14.py:使用单引号与双引号设置与输出字符串数据的应用。
执行结果
3-4-1 字符串的连接
数学的运算符“+”,可以进行两个字符串相加的操作,产生新的字符串。
程序实例ch3_15.py:字符串连接的应用。
执行结果
3-4-2 处理多于一行的字符串
程序设计时如果字符串长度多于一行,可以使用三个单引号(或是三个双引号)将字符串括起来即可。
程序实例ch3_16.py:使用三个单引号处理多于一行的字符串。
执行结果
读者可以留意第2行Silicon左边的3个单引号和第3行末端的3个单引号,另外,上述第2行若是少了"str1 = ",3个单引号间的跨行字符串就变成了程序的注释。
3-4-3 转义字符
在字符串使用中,如果字符串内有一些特殊字符,例如单引号、双引号等,必须在此特殊字符前加上“\”(反斜杠),才可正常使用,这种含有“\”符号的字符称为转义字符(Escape Character)。
字符串使用中特别是碰到字符串含有单引号时,如果是使用单引号定义这个字符串,必须要使用此转义字符,才可以顺利显示,可参考ch3_17.py的第3行。如果是使用双引号定义字符串,则可以不必使用转义字符,可参考ch3_17.py的第6行。
程序实例ch3_17.py:转义字符的应用,这个程序第9行增加了“\t”字符,所以“can’t”跳到下一个Tab键位置输出。同时有“\n”字符,这是换行符号,所以“loving”跳到下一行输出。
执行结果
3-4-4 str( )函数
str( )函数有如下几个用法。
(1)设置空字符串。
(2)设置字符串。
(3)强制将数值数据转换为字符串数据。
程序实例ch3_18.py:使用str( )函数将数值数据强制转换为字符串的应用。
执行结果
上述字符串相加,读者可以想成是字符串连接,执行结果是一个字符串,所以上述执行结果555是数值数据,222333则是一个字符串。
3-4-5 将字符串转换为整数
int( )函数可以将字符串转为整数,在未来的程序设计中也常会发生将字符串转换为整数数据,下面将直接以实例做说明。注:如果数字是非数字字符组成,会产生错误。
程序实例ch3_19.py:将字符串数据转换为整数数据的应用。
执行结果
上述执行结果55是数值数据,2233则是一个字符串。
3-4-6 字符串与整数相乘产生字符串复制效果
在Python中允许将字符串与整数相乘,结果是字符串将重复该整数的次数。
程序实例ch3_20.py:字符串与整数相乘的应用。
执行结果
3-4-7 聪明地使用字符串加法和换行字符\n
有时在设计程序时,想将字符串分行输出,可以使用字符串加法功能,在加法过程中加上换行字符“\n”即可产生字符串分行输出的结果。
程序实例ch3_21.py:将数据分行输出的应用。
执行结果
3-4-8 字符串前加r
在使用Python时,如果在字符串前加上r,可以防止转义字符被转义,可参考3-4-3节的转义字符表,相当于可以取消转义字符的功能。
程序实例ch3_22.py:字符串前加上r的应用。
执行结果
3-5 字符串与字符
在Python中没有所谓的字符(character)数据,如果字符串含一个字符,我们称这是含一个字符的字符串。
3-5-1 ASCII码
计算器内部最小的存储单位是位(bit),这个位只能存储0或1。一个英文字符在计算器中是被存储成8个位的一连串0或1中,存储这个英文字符的编码称为ASCII(American Standard Code for Information Interchange,美国信息交换标准程序代码),有关ASCII码的内容可以参考附录E。
在这个ASCII表中由于是用8位定义一个字符,所以使用了0~127定义了128个字符,在这128个字符中有33个字符是无法显示的控制字符,其他则是可以显示的字符。不过有一些应用程序扩充了功能,让部分控制字符可以显示,例如,扑克牌花色、笑脸等。至于其他可显示字符有一些符号,例如+、-、=、0~9、A~Z或a~z等。这些符号每一个都有一个编码,我们称这个编码是ASCII码。
可以使用下列函数执行数据的转换。
chr( x ):返回函数x值的ASCII或Unicode字符。
例如,从ASCII表可知,字符a的ASCII码值是97,可以使用下列方式打印出此字符。
英文小写与英文大写的码值相差32,可参考下列实例。
3-5-2 Unicode码
计算机是美国发明的,因此ASCII码对于英语系国家的确很好用,但是地球是一个多种族的社会,存在几百种语言与文字,ASCII所能容纳的字符是有限的,只要随便一个不同语系的外来词,例如,含重音字符就无法显示了,更何况有几万中文字或其他语系文字。为了让全球语系的用户可以彼此用计算机沟通,因此有了Unicode码。
Unicode码的基本精神是,世上所有的文字都有一个码值,可以参考下列网页:
http://www.unicode.org/charts
目前,Unicode内定义了超过11万的文字,它的定义方式是以“\u”开头后面有4个十六进制的数字,所以是从“\u0000”至“\uFFFF”。在上述网页中可以看到不同语系表,其中,East Asian Scripts字段可以看到CJK(Chinese,Japanese,Korean),在这里可以看到汉字的Unicode码值表,CJK统一汉字的编码为4E00~9FBB。
在Unicode编码中,前128个码值是保留给ASCII码使用,所以对于原先存在ASCII码中的英文大小写、标点符号等,是可以正常在Unicode码中使用的,Unicode编码中经常用的是ord( )函数。
ord( x ):可以返回函数字符参数x的Unicode码值,如果是中文字也可返回Unicode码值。如果是英文字符,Unicode码值与ASCII码值是一样的。有了这个函数,可以很轻易地获得字符的Unicode码值。
程序实例ch3_23.py:这个程序首先会将整数97转换成英文字符‘a’,然后将字符‘a’转换成Unicode码值,最后将中文字‘魁’转成Unicode码值。
执行结果
3-5-3 utf-8编码
utf-8是针对Unicode字符集的可变长度编码方式,这是Internet目前所遵循的编码方式,在这种编码方式下,utf-8使用1~4个byte表示一个字符,这种编码方式会根据不同的字符变化编码长度。
ASCII使用utf-8编码规则
对于ASCII字符而言,基本上它使用1个byte存储ASCII字符,utf-8的编码方式是byte的第一个位是0,其他7个位则是此字符的ASCII码值。
中文字的utf-8编码规则
对于需要n个byte编码的Unicode汉字字符而言,例如需要3个byte编码的汉字,第一个byte的前n(3)位皆设为1,n+1(4)设为0。后面第2和第3个byte的前2位是10,其他没有说明的二进制全部是此汉字字符的Unicode码。依照此规则,可以得到汉字的utf-8编码规则如下:
1110xxxx 10xxxxxx 10xxxxxx # xx就是要填入的Unicode码
例如,从ch3_23.py的执行结果可知“魁”的Unicode码值是0x9b41,如果转成二进制方式则如下所示:
10011011 01000001
我们可以用下列更细的方式,将“魁”的Unicode码值填入xx内。
从上图可以得到“魁”的utf-8编码结果是0xe9ad81,3-6-1节的实例2也可以验证这个结果。
3-6 bytes数据
使用Python处理一般字符串数据时,可以很放心地使用Unicode字符串str数据类型,至于Python内部如何处理可以不用理会,这些事情Python的直译程序会处理。
但是有一天需要与外界沟通或交换数据时,特别是我们使用中文,如果不懂中文字符串与bytes数据的转换,所获得的数据将会是乱码。例如,设计电子邮件的接收程序,所接收的可能是bytes数据,这时必须学会将bytes数据转成Unicode字符串,否则会有乱码产生。或是有一天你要设计供中国人使用的网络聊天室,必须设计将使用者所传送的Unicode中文字符串转成bytes数据传上聊天室,然后也要设计将网络接收的bytes数据转成Unicode中文字符串,这个聊天室才可以顺畅使用。
bytes数据格式是在字符串前加上b,例如,下列是“魁”的bytes数据。
b'\xe9\xad\x81'
如果是英文字符串的bytes数据格式,相对单纯地会显示原始的字符,例如,下列是字符串“abc”的bytes数据。
b'abc'
3-6-1 Unicode字符串转成bytes数据
将Unicode字符串转成bytes数据称为编码(encode),所使用的是encode( )函数,这个方法的参数是指出编码的方法,可以参考下列表格。
如果Unicode字符串是英文则转成bytes数据相对容易,因为对于utf-8格式编码,Unicode也是用一个byte存储每个字符串的字符。
实例1:英文Unicode字符串数据转成bytes数据。
假设有一个字符串string,内容是‘abc’,可以使用下列方法设置,同时检查此字符串的长度。
下面将Unicode字符串string用utf-8编码格式转成bytes数据,然后列出bytes数据的长度、数据类型,以及bytes数据的内容。
实例2:中文Unicode字符串数据转成bytes数据。
假设有一个字符串name,内容是‘洪锦魁’,可以使用下列方法设置,同时检查此字符串的长度。
下面将Unicode字符串name用utf-8编码格式转成bytes数据,然后列出bytes数据的长度、数据类型,以及bytes数据的内容。
由上述数据可以得到原来Unicode字符串用了3byte存储一个中文字,所以3个中文字获得了bytes的数据长度是9。
3-6-2 bytes数据转成Unicode字符串
对于一个专业的Python程序设计师而言,常常需要从网络取得数据,所取得的是bytes数据,这时需要将此数据转成Unicode字符串,将bytes数据转成Unicode字符串可以称为译码,所使用的是decode( )函数,这个方法的参数是指出编码的方法,与encode( )函数相同。
实例1:bytes数据转成Unicode字符串数据。
实例2:bytes数据转成Unicode字符串数据。
下面是将nameBytes数据使用utf-8编码格式转成Unicode字符串的方法,同时列出字符串长度和字符串内容。
3-7 专题——地球到月球时间计算/计算坐标轴两点之 间的距离
3-7-1 计算地球到月球所需时间
马赫是音速的单位,主要是为了纪念奥地利科学家恩斯特·马赫(Ernst Mach)而命名,一马赫就是一倍音速,它的速度大约是每小时1225千米。
程序实例ch3_24.py:从地球到月球约384 400千米,假设火箭的速度是一马赫,设计一个程序计算需要多少天、多少小时才可抵达月球。这个程序省略分钟数。
执行结果
由于尚未介绍完整的格式化程序输出,所以使用上述方式输出,第4章会改良上述程序。Python之所以可以成为当今最流行的程序语言,主要是它有丰富的函数库与方法,上述求商(第5行)和余数(第6行),在2-9节中介绍了divmod( )函数,其实可以用divmod( )函数一次取得商和余数,如下:
商, 余数 = divmod(被除数, 除数) # 函数方法 days, hours = divmod(total_hours, 24) # 本程序应用方式
程序实例ch3_25.py:使用divmod( )函数重新设计ch3_24.py。
执行结果 与ch3_24.py相同。
3-7-2 计算坐标轴两个点之间的距离
有两个点坐标分别是(x1, y1)、(x2, y2),这两个点的距离计算公式如下。
可以将上述公式转成下列计算机数学表达式。
dist = ( (x1 – x2)2 + (y1 – y2)2 ) ** 0.5 # ** 0.5相当于开根号
在人工智能的应用中,常用点坐标代表某一个对象的特征(feature),计算两个点之间的距离,相当于可以了解物体间的相似程度。距离越短代表相似度越高,距离越长代表相似度越低。
程序实例ch3_26.py:有两个点坐标分别是(1, 8)与(3, 10),请计算这两个点之间的距离。
执行结果
习题
1. 假设a是10,b是 18,c是5,请计算下列执行结果,取整数结果。(3-2节)
(a) s = a + b – c
(b) s = 2 * a + 3 – c
(c) s = b * c + 20 / b
(d) s = a % c * b + 10
(e) s = a ** c – a * b * c
2. 请重新设计第2章习题2,请使用int( )函数,以整数列出本金和。(3-2节)
3. 请重新设计第2章习题2,使用round( )函数,以整数列出本金和。(3-2节)
4. 地球和月球的距离是384 400千米,假设火箭飞行速度是每分钟250千米,请问从地球飞到月球需要多少天、多少小时、多少分钟,请舍去秒钟。(3-2节)
5. 请列出你自己名字十进制的Unicode码值。(3-5节)
6. 请列出你自己名字十六进制的Unicode码值。(3-5节)
7. 请将Unicode字符串“Python王者归来”转成bytes数据,然后输出bytes数据。(3-6节)
8. 重新设计ch3_25.py,需计算至分钟与秒钟数。(3-7节)
9. 请修改ch3_26.py,计算这两个点坐标(1, 8)与(3, 10)距坐标原点(0, 0)的距离。