



在Python中,数据类型由当下储存的值决定。数据类型分为数值(Numeric)、字符串(String)和容器(Container)。
● 数值:用于存储可计算的数值,可以分为整数、浮点数、复数等。
● 字符串:由数字、文字、特殊符号所组成的一串字符,用单引号、双引号成对标记。
● 容器:由一个以上的数据组成,依照特性可以分为列表、元组、字典、集合。
数值类型(Numeric type)可以分为整数、浮点数、复数、布尔值几种。Python可以处理任意大小的整数且保证精确,但是浮点数运算因为数据结构不同则可能会有误差。每种类型的变量都会被储存在内存中。某一种类型的数值已经超过此类型能够保存的数值范围的现象称为溢出(Overflow)。常见的溢出错误信息如Out of range或Result too large。
在Python中,变量在必要的时候可自动被转换成布尔变量(True、False)。转换法则如图2.7所示。
图2.7 布尔变量的转换法则
“=”是赋值运算,用于把右边的值存储到左边的变量中。在以下示例中,程序首先将20存到变量a中;也可以多值赋值,如将5.5、True分别存到变量b、c中。当存取到一个没有赋值的变量值时,程序会输出“not defined”的错误信息,表示该变量尚未存在。
1 a = 20 2 b, c = 5.5, True 3 4 print(a, b, c) 5 # 20, 5.5, True 6 7 print(d) 8 # Traceback (most recent call last): 9 # File "<stdin>", line 1, in <module> 10 # NameError: name 'd' is not de fi ned
下面介绍一些与类型有关的函数:type用于取得变量的类型,isinstance用于判断某一变量是否是某一种类型。用户也可以直接用int()或float()等类型作为函数对数值进行类型转换。
1 print(type(a), type(b), type(c), type(d)) 2 # <class 'int'><class ' float'><class 'bool'><class 'complex'> 3 print(type(a) == int, type(a) == float) 4 # True, False 5 print(isinstance(a, int), isinstance(b, int)) 6 # True, False 7 8 int(4.0) # 4 9 float(4) # 4.0
数值数据的基本运算有四则运算(加、减、乘、除)、次方运算(**)、取余数运算(%)、整数除法运算(//)。在运算过程中,如果数值类型不同,程序会自动取数值范围大的类型。
1 4 + 2 # 6 2 4.0 + 2 # 6.0 3 4.0 + 2.0 # 6.0 4 5 2 / 5 # 0.4 6 2.0 / 5 # 0.4 7 2 / 5.0 # 0.4 8 2.0 / 5.0 # 0.4 9 2 // 5 # 0
下面介绍与运算有关的函数:abs是绝对值函数,round是四舍五入函数。
1 n = -3.14 2 abs(n) # 3.14 3 round(n) # -3
利用引号(单引号或双引号)引起来的部分代表字符串。字符串(String type)是由数字、文字、特殊符号所组成的一串字符。
1 a = 'hello world' 2 b = '1234' 3 c = '\n' 4 d = r'\n' 5 e = '\\n' 6 7 print(a + b + c + d + e) 8 # hello world1234 9 # \n\n 10 print(a, b, c, d, e) 11 # hello world 1234 12 # \n \n
当使用print()函数输出多个数值时,多个数值之间可以用逗号隔开(预设会用空格隔开)。字符串的加法运算是先将5个字符串相连后再输出。Python的常见特殊字符如表2.2所示。
表2.2 Python的常见特殊字符
字符串可以利用索引(Index)取得某一位置上的值(将[]接在变量之后),如图2.8所示。在Python程序当中,位置是从0开始的。切片(Slicing)运算是指可以在[]当中利用“:”取一个范围之内的子字符串。当切片有第三个值时,第三个值代表切片的间隔。
图2.8 字符串符与索引
1 a = 'hello world'
2 a[0], a[1], a[2]
3 # ('h', 'e', 'l')
4 a[0:5], a[0:len(b)], a[:]
5 # ('hello', 'hell', 'hello world')
6 a[1:5:2], a[::-1]
7 # ('el', 'dlrow olleh')
字符串运算只有加法运算和乘法运算,没有减法运算和除法运算。字符串的加法运算会把字符串相拼,乘法运算会对字符串重复进行多次相拼。
1 a = 'hello world' 2 a + '_' 3 # 'hello world_' 4 a * 2? 5 # 'hello worldhello world'
字符串和数值是不能相加的。
1 a + 2 2 # Traceback (most recent call last): 3 # File "<stdin>", line 1, in <module> 4 # TypeError: must be str, not int
下面介绍一些常用的字符串函数。
1 split() # 字符串分割 2 find() # 寻找子字符串 3 replace() # 子字符串取代 4 len() # 计算字符串长度 5 lower() # 字符串转小写 6 upper() # 字符串转大写 7 isnumeric() # 是否为数字字符串 8 isalpha() # 是否为字母字符串
格式化字符串(String Formatting)是一种特殊的字符串,用于在字符串中插入变量。在传统方法中,用户可以用加法或逗号实现在字符串中插入变量,但容易让程序变得过于杂乱而难以维护。格式化字符串的目的是将字符串与变量隔离,在执行时才将变量插入字符串。以下示范几种做法。
1 print('%s %s' % ('one', 'two'))
2 # one two
3 print('{} {}'.format('one', 'two'))
4 # one two
前面的方法虽然可以将变量隔离,但还是要在同一行语法中设置变量。3.6+版本引入了一种新的写法,能够在字符串中直接使用全局变量。
1 a = 'one'
2 b = 'two'
3 print(f'{a} {b}')
4 # one two
数值或字符串都是原子类型,都只是单一值的数据类型;容器(Container type)则能够在一个变量中存放一个以上的数值(称为元素)。在Python中,容器类型有4种。
● 列表(List):有序且可变的容器。
● 元组(Tuple):有序但不可变的容器。
● 字典(Dict):Key-Value对应的组合容器。
● 集合(Set):无序且包含不可以重复元素的组合容器。
列表用[…]表示,里面可以放多个数值。在下面的例子中,第一行表示有一个名为L的列表,其内容由1、2、3、4、5、6六个元素组成。与字符串类似,在列表中,用户可以用索引的方式取到数据。第二行表示取出L列表中第0个、第1个、倒数第1个(-1代表倒数)元素,分别是1、2、6。第三行表示可以用赋值运算把第0个元素改成999。第四、第五行是切片功能,表示用户可以在索引中使用“:”取一个范围之内的子列表。
1 L = [1, 2, 3, 4, 5, 6]
2 L[0], L[1], L[-1]
# (1, 2, 6)
3 L[0] = 999
4 L[0:5], L[0:len(L)], L[:]
# ([1, 2, 3, 4, 5], [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6])
5 L[1:5:2], L[::-1]
# ([2, 4], [6, 5, 4, 3, 2, 1])
在运算方面,列表支持加法运算和乘常数运算,不支持减法运算和除法运算。加法运算会将多个列表连接起来,乘常数运算会将同一个列表重复多次。
1 L = [1, 2, 3, 4] 2 G = [5, 6, 7, 8] 3 4 L + G 5 # [1, 2, 3, 4, 5, 6, 7, 8] 6 7 L - G 8 # Traceback (most recent call last): 9 # File "<stdin>", line 1, in <module> 10 # TypeError: unsupported operand type(s) for -: 'list' and 'list' 11 12 L * 2 13 # [1, 2, 3, 4, 1, 2, 3, 4] 14 15 L / 2 16 # Traceback (most recent call last): 17 # File "<stdin>", line 1, in <module> 18 # TypeError: unsupported operand type(s) for /: 'list' and 'int'
列表的函数有多种。L.append(2)用于将参数2加到L列表的最后一位。与L.append(2)相似的L.extend([1,2,3])方法则是将参数[1,2,3]列表中的每一个元素都加到L列表的元素中。insert()用于将某一数据插入列表,它有两个参数,一个参数代表插入的位置,另一个参数代表插入的数值。例如,L.insert(0,3)表示将3插入L[0]的位置,其余数值依次往右平移。
删除数据有两种方法:pop()和remove()。L.pop()用于将L最右边的数据删除,可以设置一个变量去补充删除位置的数据。L.remove(2)用于将L中第一个出现的2删除。L.sort()用于将L由小至大排序,L.reverse()用于将L反序排列。
1 L = [2] # [2] 2 L.append(2) # [2, 2] 3 L.extend([2]) # [2, 2, 2] 4 L.insert(0, 3) # [3, 2, 2, 2] 5 L.pop() # [3, 2, 2] 6 L.remove(2) # [3, 2] 7 L.sort() # [2, 3] 8 L.reverse() # [3, 2]
有几组方法需要我们对比看一下。
1 L.extend([2]) 2 L + [2] 3 4 L.reverse() 5 L[::-1] 6 7 L.sort() 8 sorted(L)
这几组都可以实现类似的行为,也就是说它们的目的是差不多的,差别在于前者会直接改变L的值,但不会返回内容,后者会显示结果,但按不会改动L本身,除非将结果再指定回去。因此,用户在使用一个函数的时候有两个关注点:一是会不会改动本身;二是返回什么内容。
最后一组常见的函数是len(L)和sum(L),分别用于计算L的长度(元素个数)和总和。L.count(2)用于计数L当中2出现的次数。
1 L = [1,2,2,3,4,5] 2 len(L) # 6 3 sum(L) # 17 4 L.count(2) # 2
前面提到有“()”的通常是函数,但函数有时候用L.sort(),有时候用sorted(L),这两种用法有什么差异?前者的sort()是L下的函数,专属于L;后者的sorted()是Python内建的,可以将L当成参数传进去,也可以将其他可数容器传进去,是通用的。这两种的用法不一样,主要是因为它们定义的层级不同。
1 L = [] 2 sorted 3 # <built-in function sorted> 4 sort 5 # Traceback (most recent call last): 6 # File "<stdin>", line 1, in <module> 7 # NameError: name 'sort' is not de fi ned 8 L.sort 9 # <built-in method sort of list object at 0x10dcb2988>
元组的用法与列表类似,只是用“( )”而不是用“[ ]”。元组和列表都是有序的容器,差别是元组内的数据是不可以改变的。
1 # tuple 2 T = (1, 2, 3, 4, 5, 6) 3 T[0], T[1], T[-1] 4 # (1, 2, 6) 5 T[0] = 999 6 # Traceback (most recent call last): 7 # File "<stdin>", line 1, in <module> 8 # TypeError: 'tuple' object does not support item assignment
元组有两个常见的用法(其实列表也支持)。第一个用法是解构,可以将一个tuple分配到多个变量。下面的例子中有一个由三个元素组成的元组a,可以将三个元素一次指定给x、y、z三个变量。第二个用法是交换变量,可以用(x,y)=(y,x)的方式达到交换x、y的效果。
1 # 解构 2 a = (1, 2, 3) 3 x, y, z = a 4 5 # 交换变量 6 (x, y) = (y, x)
解构(Destruction)和展开(Spread)是容器运算,能够把容器的数据指定到多元素或合并。展开的用法是在容器中使用“**”符号,将变量展开成元素。
1 data = [1,2,3]
2 a, b, c = data
3 data = (1, 2, 3)
4 a, b, c = data
5
6 a = [1, 2, 3]
7 b = [2, 3, 4]
8 c = [**a, **b]
9
10 a = {'a': 1, 'b': 2, 'c': 3]
11 b = {'c': 2, 'd': 3, 'e': 4}
12 c = {**a, **b}
字典是一种无序的容器数据。因为无序而无法用索引来选取数据,字典必须采用key做定位。因此,字典的每一个元素都是一个key与value组合,使用{ }来初始化。下面的例子定义了一个由两个元素'Mark': 1、'test': 0组成的字典,其key是Mark和test,value是1,2。我们可以利用索引的方式新增数据,如d['Mary'] = 2;用del d['test']的方式把特定key的数据删除。
1 d = {'Mark': 1, 'test': 0}
2 d['Mary'] = 2
3 del d['test']
字典的第一个重点是无序转有序。
1 my_dict.items()
2 # dict_items([('Mark', 1), ('Mary', 2) ])
3 my_dict.keys()
4 # dict_keys(['Mark', 'Mary'])
5 my_dict.values()
6 # dict_values([1, 2])
字典的另一个重点是存取不存在的数据。当用户试图存取my_dict['Tom']时,程序会报错—KeyError,表示该key不存在于my_dict当中。用户可以使用get()或setdefault()两个函数来辅助存取,当key存在时回传value,当key不存在时返回空,差别在于setdefault()除了回传数据,也会把该笔数据写入字典,避免下一次错误。
1 my_dict['Tom']
2 # Traceback (most recent call last):
3 # File "<stdin>", line 1, in <module>
4 # KeyError: 'Tom'
5
6 my_dict.get('Tom', ''), my_dict
7 # '', {'Mark': 1, 'test': 0}
8
9 my_dict.setdefault('Tom', 3), my_dict
10 # 3, {'Tom': 3, 'Mark': 1, 'test': 0}
集合一种Python内建的容器类型,类似于数学中的集合。它是一种无序且元素不重复的数据类型,有交集运算、连集运算、差集运算和对称差运算。实际上,集合常用于去除重复数据。
1 admins = {'admin'} # 建立 set
2 users = {'admin', 'user1', 'user2'}
3
4 'Justin' in admins # True
5 admins & users # {'admin'}
6 admins | users # {'admin', 'user1', 'user2'}
7 admins - users # {}
8 admins ^ users # {user1, user2}
在Python中,数据类型还可以依照性质可否改变分成可变(Mutable)类型和不可变(Immutable)类型。
● Mutable objects => list, dict, set
● Immutable objects => int, float, complex, string, tuple
与其他程序语言不同,Python的运算符“=”不只是赋值运算,还是引用。因此,x = 2的意义是建立2的整型数值对象,再将变量x指向该对象的地址(引用),所以把整型这类原子类型定位成不可变的(Immutable)。