前言

这部分会再前面涉及的数据结构的基础上拓展并且说明更多的数据结构,这些数据结构在编程方面就如图画家的画笔,是编程工具或者说小帮手。

✒️:现在需要说明一个事情,且后面不会再强调说明:如果方法签名中某些参数两边的方括号([])表示这个参数是可选的,而不是要你输入方括号。你会在 Python 参考库中经常看到这种表示方法

列表的更多特性

前面已经说明了列表的基本概述,其还有很多的方法,如下所示:

方法 说明
list.append(x) 在列表的末尾添加一个元素
list.extend(iterable) 使用可迭代对象中的所有元素来扩展列表
list.insert(i, x) 在给定的位置插入一个元素。第一个参数是要插入的元素的索引,第二个参数是要插入的元素
list.remove(x) 移除列表中第一个值为 x 的元素。如果没有这样的元素,则抛出 ValueError异常
list.pop([i]) 删除列表中给定位置的元素并返回它。如果没有给定位置,a.pop() 将会删除并返回列表中的最后一个元素
list.clear() 移除列表中的所有元素
list.index(x[,start[,end]]) 返回列表中第一个值为 x 的元素的从零开始的索引。如果没有这样的元素将会抛出 ValueError 异常
可选参数startend是切片符号,用于将搜索限制为列表的特定子序列。返回的索引是相对于整个序列的开始计算的,而不是 start 参数
list.count(x) 返回元素 x 在列表中出现的次数
list.sort(*,key=None,reverse=False) 对列表中的元素进行排序(参数可用于自定义排序,解释请参见 sorted
list.reverse() 翻转列表中的元素
list.copy() 返回列表的一个浅拷贝

列表作为栈使用

列表方法使得列表作为堆栈非常容易,最后一个插入,最先取出(“后进先出”)。要添加一个元素到堆栈的顶端,使用 append() 。要从堆栈顶部取出一个元素,使用 pop() ,不用指定索引。

关于栈的说明,可以参考数据结构-栈

列表作为队列使用

列表也可以用作队列,其中先添加的元素被最先取出 (“先进先出”);然而列表用作这个目的相当低效。因为在列表的末尾添加和弹出元素非常快,但是在列表的开头插入或弹出元素却很慢 (因为所有的其他元素都必须移动一位)。

若要实现一个队列,可使用 collections.deque,它被设计成可以快速地从两端添加或弹出元素。

列表推导式

列表推导式提供了一个更简单的创建列表的方法。常见的用法是把某种操作应用于序列或可迭代对象的每个元素上,然后使用其结果来创建列表,或者通过满足某些特定条件元素来创建子序列。

例如,假设我们想创建一个平方列表,像这样

1
2
3
4
5
6
>>> squares = []
>>> for x in range(10):
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

del语句

有一种方式可以从列表按照给定的索引而不是值来移除一个元素: 那就是 del 语句。 它不同于会返回一个值的 pop() 方法。 del 语句也可以用来从列表中移除切片或者清空整个列表(我们之前用过的方式是将一个空列表赋值给指定的切片)。 例如:

1
2
3
4
5
6
7
8
9
10
>>> 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 也可以删除整个变量

1
del a

此后再引用 a 时会报错。

元组和序列

我们看到列表和字符串有很多共同特性,例如索引和切片操作。他们是序列数据类型中的两种。随着 Python 语言的发展,其他的序列类型也会被加入其中。这里介绍另一种标准序列类型: 元组

一个元组由几个被逗号隔开的值组成,例如

1
2
3
4
5
6
7
8
>>> 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))

如你所见,元组在输出时总是被圆括号包围的,以便正确表示嵌套元组。输入时圆括号可有可无,不过经常会是必须的(如果这个元组是一个更大的表达式的一部分)。给元组中的一个单独的元素赋值是不允许的,当然你可以创建包含可变对象的元组,例如列表。

虽然元组可能看起来与列表很像,但它们通常是在不同的场景被使用,并且有着不同的用途。元组是 immutable ,其序列通常包含不同种类的元素,并且通过解包或者索引来访问。列表是 mutable ,并且列表中的元素一般是同种类型的,并且通过迭代访问。

语句 t = 12345, 54321, 'hello!' 是元组打包的一个例子:值 12345, 54321'hello!' 被打包进元组。其逆操作也是允许的:

1
>>> x, y, z = t

这被称为序列解包也是很恰当的,因为解包操作的等号右侧可以是任何序列。序列解包要求等号左侧的变量数与右侧序列里所含的元素数相同。注意多重赋值其实也只是元组打包和序列解包的组合。

总结来说,元组和列表的区别如下:

  1. 不可变性:元组是不可变的,即元组一旦创建,就不能对其进行修改,如添加或删除元素。而列表是可变的,可以对其进行修改操作。
  2. 表示方式:元组使用圆括号()进行表示,例如:my_tuple = (1, 2, 3);而列表使用方括号([])表示,例如:my_list = [1, 2, 3]
  3. 性能:元组的存储空间相对较小,操作速度也比列表快,因为不需要为了维护元素改变而分配额外内存。
  4. 方法:由于列表是可变类型,它具有更多的方法,如append、pop等。而元组只有两个方法:index和count,这是由它们的不可变性决定的。

集合

集合是由不重复元素组成的无序的集。它的基本用法包括成员检测和消除重复元素。集合对象也支持像 联合,交集,差集,对称差分等数学运算。

花括号或 set()函数可以用来创建集合

注意:要创建一个空集合你只能用 set() 而不能用 {},因为后者是创建一个空字典。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket)
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket
True
>>> 'crabgrass' in basket
False

>>> 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'}

总结来说,集合和列表的区别如下:

  1. 无序性:集合中的元素是无序的,而列表中的元素是有序的。在集合中,元素的顺序是不重要的。
  2. 唯一性:集合中的元素是唯一的,不允许出现重复元素。列表则允许存储重复元素。
  3. 可变性:集合和列表都是可变的数据类型,允许添加、删除和修改元素。
  4. 表示方式:集合使用花括号({})表示,例如:my_set = {1, 2, 3}。但如果创建空集合,需要使用set(),如:empty_set = set()。列表使用方括号([])表示,例如:my_list = [1, 2, 3]
  5. 数据类型:集合只支持存储不可变类型(如整数、字符串、元组)的数据,而列表可以存储任何数据类型。
  6. 操作:集合支持集合间的一些数学操作,如交集、并集、差集等。列表不支持这些操作。

字典

字典是一个特殊类型的列表,与以连续整数为索引的序列不同,字典是以关键字为索引的,关键字可以是任意不可变类型,通常是字符串或数字。如果一个元组只包含字符串、数字或元组,那么这个元组也可以用作关键字。但如果元组直接或间接地包含了可变对象,那么它就不能用作关键字。

理解字典的最好方式,就是将它看做是一个 键: 值 对的集合,键必须是唯一的(在一个字典中)。一对花括号可以创建一个空字典:{}另一种初始化字典的方式是在一对花括号里放置一些以逗号分隔的键值对,而这也是字典输出的方式。

字典主要的操作是使用关键字存储和解析值。也可以用 del 来删除一个键值对。如果你使用了一个已经存在的关键字来存储值,那么之前与这个关键字关联的值就会被遗忘。用一个不存在的键来取值则会报错。

对一个字典执行 list(d)返回包含该字典中所有键的列表,按插入次序排列 (如需其他排序,则要使用 sorted(d))。要检查字典中是否存在一个特定键,可使用 in 关键字。

注:直接使用in关键字如下所示,在控制台中会输出True,在 IDE 中我们可以使用print来输出结果。

代码示例如下:

1
2
3
4
5
6
7
8
9
10
>>> a = {'key1': 2, "test2": 1, "key3": "你好"}
>>> print(a)
{'key1': 2, 'test2': 1, 'key3': '你好'}
>>> print(list(a))
['key1', 'test2', 'key3']
>>> a = {'key1': 2, "test2": 1, "key3": "你好"}
>>> 'key1' in a
True
>>> '1' in a
False

dict() 构造函数可以直接从键值对序列里创建字典。

1
2
3
>>> b = dict([("key1",1),("key2",2)])
>>> b
{'key1': 1, 'key2': 2}

当关键字是简单字符串时,有时直接通过关键字参数来指定键值对更方便。

1
2
3
>>> b = dict(key1 = 1,key2 = 2,key3='text') 
>>> b
{'key1': 1, 'key2': 2, 'key3': 'text'}

循环的技巧

当在字典中循环时,用 items() 方法可将关键字和对应的值同时取出,代码示例:

1
2
3
4
5
6
7
8
a = {'key1': 2, "test2": 1, "key3": "你好"}
for c,v in a.items():
print(c,v)

#输出结果
key1 2
test2 1
key3 你好

当在序列中循环时,用 enumerate() 函数可以将索引位置和其对应的值同时取出,代码示例:

1
2
3
4
5
6
7
8
a = ['测试','测试2','测试3']
for c,v in enumerate(a):
print(c,v)

#输出结果
0 测试
1 测试2
2 测试3

当同时在两个或更多序列中循环时,可以zip() 函数将其内元素一一匹配。代码示例:

1
2
3
4
5
6
7
8
9
a = ['测试','测试2','测试3']
b = [1,2,3]
for c,v in zip(b,a):
print('num {0},content {1}'.format(c,v))

#输出结果
num 1,content 测试
num 2,content 测试2
num 3,content 测试3

使用.format()配合占位符{}可以方便的输出指定字符串

注:当需要在循环时修改列表内容,一般来说改为创建一个新列表是比较简单且安全的

条件控制

关键字:innot inandor

其使用原理和方法同其他编程语言一致,只是表达关键字改变了。此处不过多赘述。

End

这是一个结尾,最近感觉很颓废啊,少年仍需努力。