和大多数编程语言类似,Python也有很多内建数据结构,用来表示一系列有关联或者类似的数据。获取元素的方法也类似,都是通过下标,即[]包含的数字,用来找到每一个位置的元素,下标是从0开始。但是和大多数编程语言不同的是,Python的数据结构可以存储不同数据类型,而其他语言类型必须保持一致。下标方面,Python有一大特色功能,就是切片,而且Python下标支持负数索引,-1指定最后一个元素,往前类推。
元组
一种固定长度、不可变的对象序列,通过小括号或者tuple关键字创建元组对象。元组可以通过加法乘法得到新的元组对象,把内容相加或乘以多份。元组在Python中很多地方都会用到,包括函数返回多个值的时候,实质上返回的是一个元组,以及同时给多个变量赋不同的值,本质上也是将右边的值打包成元组。
注意的是,元组本身的元素是不可变的,但是如果元组包含的是引用的值的话,可以去改变引用所指向的值,而不会产生错误。
a = (1, 2, 3) # 或者a = tuple([1, 2, 3])
b = a * 2 # (1, 2, 3, 1, 2, 3)
c = (1, [2, 3])
c[2].append(4) # 正确的
print(c) # (1, [2, 3, 4])
元组拆包
元组的数据除了通过下标索引的方式获取元素,还可以根据元组的个数,一次性赋给相同个数的变量。还可以通过在变量前增加*来获取不定长的元素。
a = (1, 2, 3)
b, c, d = a # b == 1, c == 2, d == 3
e, *f = a # e == 1, f == (2, 3)
元组方法
因为元组不可变,所以方法相对比较少,一个常见方法是count,计算元组中某一个元素的出险次数。
a = (1, 1, 2, 2, 2, 3, 4)
a.count(2) # 3
列表
一种可变长、元素可变的对象序列,通过中括号或者list关键字创建列表对象。
a = [1, 2, 3] # 或者a = list([1, 2, 3])
增加和移除元素
append方法可以在列表最后添加一个元素,insert方法可以在指定位置添加元素,这两个相比,insert方法明显更加方便,但是在内存消耗更高。
pop方法用来移除某一位置的元素,同时函数会返回元素值,remove方法用来移除特定内容的元素,如果有重复的元素,会移除第一个对应元素。
通过in和not in可以判断某一元素是否在列表中。
连接和联合列表
列表也可以通过加法连接多个列表,因为列表是可变的,所以可以通过extend方法将一个列表里的所有值添加到另一个列表里去。使用extend方法会比直接连接消耗更少的内存。
排序
通过调用sort方法可以根据给定的比较方法对列表进行排序,这个操作是原地完成的。
*二分搜索和已排序列表的维护
bisect模块提供了二分搜索的一些方法,其中bisect方法可以在已排序列表中查找元素应当查找的位置,insort方法将元素插入到相应的位置。
注意的是,这个模块并不会检查列表是否已经排序完成,所以需要在编程的时候注意。
切片
通过在索引的时候使用[start:stop:step]获得列表中某一部分的元素,包含start不包含stop,不提供start表示从列表第一个开始取,不提供stop表示取到列表最后一个,step表示每隔多少个进行取值,这三者都可正可负。
内建序列函数
enumerate
根据列表元素生成迭代器,每次遍历同时获得元素及元素索引。
a = ['a', 'b', 'c']
for i, c in enumarate(a):
print('num: {}, letter: {}'.format(i,c))
# num: 1, letter: 'a'
# num: 2, letter: 'b'
# num: 3, letter: 'c'
sorted
根据列表返回新建已排序列表,和列表的sort方法不同,sorted需要接受一个列表作为参数,并且会返回一个新列表,而不是在原地进行排序。
zip
将多个列表元素按序配对成元组,元组个数跟最短列表的长度一致,返回由这些元组组成的列表。
a = [1, 2, 3]
b = ['a', 'b', 'c']
c = [True, False]
d = zip(a, b, c) # [(1, 'a', True), (2, 'b', False)]
reversed
将一个序列元素倒序排列,并返回一个生成器,可以用来生成列表或者进行循环。
字典
dict的每个元素都是由键值对组成,可以通过dict方法创建字典对象,虽然字典输出时会以大括号形式输出,但是不能使用大括号进行创建。一个字典的键都是唯一的,它通过索引获取值的时候,下标不是元素的位置,而是元素对应的键。可以通过del或者pop根据键删除对应的值,pop方法会返回相应的值。可以用in检查是否包含某个键。
keys方法和values方法返回键和值的迭代器,顺序不是特定的但是两者的顺序会是一致的。
update方法可以合并新的字典内容,如果有相同的键,原来的值会被覆盖。
从序列生成字典
比较直接的方法是使用zip方法合并两个序列,分别指定为键和值。
默认值
获取字典值的时候,可以设置默认值,用来给新添加的键赋默认值。
有效的字典键类型
字典的键本质上是以哈希的方式进行存储,所以字典的键必须得满足能够被哈希化,在能够作为字典的键,这就要求字典的键必须是不可变的。
集合
一种无序且元素唯一的容器,可以通过set方法或者大括号创建集合对象。集合支持数学上关于集合的大部分操作,包括交集、并集、补集等。
函数 | 替代方法 | 描述 |
---|---|---|
a.add(x) | - | 将元素x加入元素a |
a.clear() | - | 将集合重置为空,清空所有元素 |
a.remove(x) | - | 从集合a移除某个元素 |
a.pop() | - | 移除任意元素,如果集合是空的抛出KeyError |
a.union(b) | a | b | a和b中的所有不同元素 |
a.update(b) | a |= b | 将a的内容设置为a和b的并集 |
a.intersection(b) | a & b | a、b中同时包含的元素 |
a.intersection_update(b) | a &= b | 将a的内容设置为a和b的交集 |
a.difference(b) | a - b | 在a不在b的元素 |
a.difference_update(b) | a -= b | 将a的内容设为在a不在b的元素 |
a.symmetric_difference(b) | a ^ b | 所有在a或b中,但不是同时在a、b中的元素 |
a.symmetric_difference_update(b) | a ^= b | 将a的内容设为所有在a或b中,但不是同时在a、b中的元素 |
a.issubset(b) | - | 如果a包含于b返回True |
a.issuperset(b) | - | 如果a包含b返回True |
a.isdisjoint(b) | - | a、b没有交集返回True |
列表、集合和字典的推导式
Python的奇技淫巧语言特性之一,通过推导式可以快速生成序列对象。本质上是一个循环语句块。
列表推导式:[expr for val in collection (if condition)] 字典推导式:{key_expr : value_expr for value in collection (if condition)} 集合推导式:{expr for val in collection (if condition)}
嵌套列表推导式
可以通过多个for循环做到对复杂序列遍历得到所需结构,也可以将表达式也替换成推导式生成多维序列。嵌套方法比较方便,但是相对来说牺牲了一定的可读性。