数据结构
- 不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
- 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
1 列表
方法 | 解释 |
---|---|
append(x) | 在列表末尾添加一个元素,相当于 a[len(a):] = [x] 。 |
extend(iterable) | 用可迭代对象的元素扩展列表。相当于 a[len(a):] = iterable 。 |
insert(i, x) | 在指定位置插入元素。第一个参数是插入元素的索引,因此,a.insert(0, x) 在列表开头插入元素, a.insert(len(a), x) 等同于 a.append(x) 。 |
remove(x) | 从列表中删除第一个值为 x 的元素。未找到指定元素时,触发 ValueError 异常。 |
pop([i]) | 删除列表中指定位置的元素,并返回被删除的元素。未指定位置时,a.pop() 删除并返回列表的最后一个元素。(方法签名中 i 两边的方括号表示该参数是可选的,不是要求输入方括号。这种表示法常见于 Python 参考库)。 |
clear() | 删除列表里的所有元素,相当于 del a[:] 。 |
index(x[, start[, end]]) | 返回列表中第一个值为 x 的元素的零基索引。未找到指定元素时,触发 ValueError 异常。可选参数 start 和 end 是切片符号,用于将搜索限制为列表的特定子序列。返回的索引是相对于整个序列的开始计算的,而不是 start 参数。 |
count(x) | 返回列表中元素 x 出现的次数。 |
sort(*, key=None, reverse=False) | 就地排序列表中的元素(要了解自定义排序参数,详见 sorted())。 |
reverse() | 翻转列表中的元素。 |
copy() | 返回列表的浅拷贝。相当于 a[:] 。 |
fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
>>> fruits.count('apple') # 2
>>> fruits.count('tangerine') # 0
>>> fruits.index('banana') # 3
>>> fruits.index('banana', 4) # 6
>>> fruits.reverse()
>>> fruits # ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
>>> fruits.append('grape')
>>> fruits # ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
>>> fruits.sort()
>>> fruits # ['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
>>> fruits.pop() # 'pear'
1.1 列表推导式
常见的用法为,
- 对序列或可迭代对象中的每个元素应用某种操作,
- 用生成的结果创建新的列表;
- 或用满足特定条件的元素创建子序列。
这种写法更简洁、易读。(???)
列表推导式的[]
内包含以下内容:
- 一个表达式,后面是零个或多个 for 或 if 子句。
结果是由表达式依据 for 和 if 子句求值计算而得出一个新列表。
例1,创建平方值的列表:
# 列表推导式
squares = [x**2 for x in range(10)]
#等价于
squares = []
for x in range(10):
squares.append(x**2)
例2,将两个列表中不相等的元素组合起来:
[(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
#等价于
combs = []
for x in [1,2,3]:
for y in [3,1,4]:
if x != y:
combs.append((x, y))
例3,转置行列(嵌套列表推导式):
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
]
[[row[i] for row in matrix] for i in range(4)] # [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
# 等价于
transposed = []
for i in range(4):
transposed.append([row[i] for row in matrix])
# 实际应用中,最好用内置函数替代复杂的流程语句。
list(zip(*matrix))
1.2 del命令
del 语句按索引,而不是值从列表中移除元素。
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a # [1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a # [1, 66.25, 1234.5]
>>> del a[:]
>>> a # []
>>> del a # 删除整个变量,再引用 a 就会报错(直到为它赋与另一个值)
2 序列:元组
序列:
- 字符串
- 列表
- 元组
元组由多个用,
隔开的值组成,
>>> t = 12345, 54321, 'hello!'
>>> t[0] # 12345
>>> t # (12345, 54321, 'hello!')
>>> u = t, (1, 2, 3, 4, 5)
>>> u # ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> v = ([1, 2, 3], [3, 2, 1])
>>> v # ([1, 2, 3], [3, 2, 1])
- 输入时,圆括号可有可无,不过经常是必须的(如果元组是更大的表达式的一部分)。
- 输出时,元组都要由圆括号标注,这样才能正确地解释嵌套元组。
- 不允许为元组中的单个元素赋值,当然,可以创建含列表等可变对象的元组。
2.1 列表与元组的区别
- 列表: mutable (可变的),列表元素一般为同质类型,可迭代访问。
- 元组: immutable (不可变的),一般可包含异质元素序列,通过解包(见本节下文)或索引访问(如果是 namedtuples,可以属性访问)。
因此,元组与列表虽然很像,但使用场景不同,用途也不同。
2.2 创建0元组和1元组
>>> empty = () # 0元组
>>> singleton = 'hello', # 1元组,结尾有个逗号
>>> len(empty) # 0
>>> len(singleton) # 1
>>> singleton # ('hello',)
2.3 元组打包和序列解包
t = 12345, 54321, 'hello!' # 元组打包
x, y, z = t # 序列解包,左侧变量与右侧序列元素的数量应相等。
多重赋值其实只是元组打包和序列解包的组合。
3 集合
集合是由不重复元素组成的无序容器。基本用法包括:
- 成员检测、
- 消除重复元素。
集合对象支持合集、交集、差集、对称差分等数学运算。
创建集合只能用 set()
!
虽然{}也可以,但它不能用在创建空集合的时候,因为那是创建空字典,因此创建集合统一使用set()。
>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
或者
>>> basket = set(('apple', 'orange', 'apple', 'pear', 'orange', 'banana')) #只能传入一个参数,可以是list,tuple等 类型
>>> print(basket) # {'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket # True
>>> 'crabgrass' in basket # False
>>> # Demonstrate set operations on unique letters from two words
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # {'a', 'r', 'b', 'c', 'd'}
>>> a - b # 差集 {'r', 'd', 'b'}
>>> a | b # 并集 {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # 交集 {'a', 'c'}
>>> a ^ b # 反交集 {'r', 'd', 'b', 'm', 'z', 'l'}
3.1 集合推导式
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a # {'r', 'd'}
4 字典
其他语言可能把字典称为 联合内存 或 联合数组。其实就是map。
与以连续整数为索引的序列不同,字典以 关键字 为索引,关键字通常是:
- 字符串,
- 或数字,
- 或只包含字符串、数字、元组的元组。
也可以是其他任意不可变类型。
但如果元组直接或间接地包含了可变对象,就不能用作关键字。
创建字典:
- 空的
{}
用于创建空字典。 - 在
{}
里输入,
分隔的键值对,这也是字典的输出方式。
使用字典:
- 用 del 可以删除键值对。
- 对字典执行 list(d) 操作,返回该字典中所有键的列表,按插入次序排列
- 排序,请使用 sorted(d)。
- 检查字典里是否存在某个键,使用关键字 in。
例子:
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel # {'jack': 4098, 'sape': 4139, 'guido': 4127}
>>> tel['jack'] # 4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel # {'jack': 4098, 'guido': 4127, 'irv': 4127}
>>> list(tel) # ['jack', 'guido', 'irv']
>>> sorted(tel) # ['guido', 'irv', 'jack']
>>> 'guido' in tel # True
>>> 'jack' not in tel # False
4.1 dict()
dict() 构造函数可以直接用键值对序列创建字典:
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
# {'sape': 4139, 'guido': 4127, 'jack': 4098}
关键字是比较简单的字符串时,直接用关键字参数指定键值对更便捷:
>>> dict(sape=4139, guido=4127, jack=4098)
# {'sape': 4139, 'guido': 4127, 'jack': 4098}
4.2 字典推导式
>>> {x: x**2 for x in (2, 4, 6)} # {2: 4, 4: 16, 6: 36}
5 序列之间的比较
序列对象可以与相同序列类型的其他对象比较。这种比较使用 字典式 顺序:
首先,比较前两个对应元素,如果不相等,则可确定比较结果;如果相等,则比较之后的两个元素,以此类推,直到其中一个序列结束。
如果要比较的两个元素本身是相同类型的序列,则递归地执行字典式顺序比较。
如果两个序列中所有的对应元素都相等,则两个序列相等。
如果一个序列是另一个的初始子序列,则较短的序列可被视为较小(较少)的序列。
对于字符串来说,字典式顺序使用 Unicode 码位序号排序单个字符。下面列出了一些比较相同类型序列的例子:
(1, 2, 3) < (1, 2, 4)
[1, 2, 3] < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4) < (1, 2, 4)
(1, 2) < (1, 2, -1)
(1, 2, 3) == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)
注意,对不同类型的对象来说,只要待比较的对象提供了合适的比较方法,就可以使用 < 和 > 进行比较。例如,混合数值类型通过数值进行比较,所以,0 等于 0.0,等等。否则,解释器不会随便给出一个对比结果,而是触发 TypeError 异常。