本文将详细介绍 Python 的六大数据结构,包括数值、字符串、列表、元组、集合、字典等。阅读本文预计需要 15 min。
数据结构对编程中非常重要的一部分,掌握 Python 数据结构非常必要。本文主要总结 Python 六大数据结构:
Python 中有 3 种数值类型,分别是整型(int)、浮点型(float)、复数型(complex)。此外布尔型(bool)是整型的子类。通过下面的例子来直观感受一下:
# 多个变量赋值
a, b, c, d = 10, 6.66, 10+5j, False
print(f"a的类型为:{type(a)}") # type(x) 可以查看 x 的类型
print(f"b的类型为:{type(b)}")
print(f"c的类型为:{type(c)}")
print(f"d的类型为:{type(d)}")
输出结果:
a的类型为:<class 'int'>
b的类型为:<class 'float'>
c的类型为:<class 'complex'>
d的类型为:<class 'bool'>
文本信息是一种非常重要的信息。在 Python 中,字符串来充当这种角色。在 Python 中字符串是不可变对象,不可以被修改,要修改只能通过重新开辟内存空间,创建新的对象来实现。
这里需要说明一下,Python 中变量更像一个标签,这个标签指向存储了数据的地址,我们可以通过 id()
函数来查看对象的内存地址。
s = 'a'
print(f's 变量的值是:{s},s 变量的地址是:{id(s)}')
s += 'b' # 等价于 s = s + 'b'
print(f's 变量的值是:{s},s 变量的地址是:{id(s)}')
结果输出:
s 变量的值是:a,s 变量的地址是:2014533253552
s 变量的值是:ab,s 变量的地址是:2014533384432
通过上面这个例子我们可以看到,字符串不可以被改变,一旦改变,内存地址就会发生变化。相当于重新赋值。
创建字符串有以下几种方式:单引号、双引号、三引号、str()函数。代码直观演示如下:
s1 = 'a' # 单引号创建单行字符串
s2 = "b" # 创建单行字符串
s3 = '''
这是三个单引号创建的
多行字符串!'''
s4 = """
这是三个双引号创建的
多行字符串!"""
s5 = str([1, 2, 3]) # [1, 2, 3] 是列表,后面会讲,这里是把列表转化为字符串
print(f'单引号创建的单行字符串内容是:{s1}')
print(f'双引号创建的单行字符串内容是:{s2}')
print(f'三个单引号创建的多行字符串内容是:{s3}')
print(f'三个双引号创建的多行字符串内容是:{s4}')
print(f'str() 函数创建的字符串内容是:{s5}')
输出结果:
单引号创建的单行字符串内容是:a
双引号创建的单行字符串内容是:b
三个单引号创建的多行字符串内容是:
这是三个单引号创建的
多行字符串!
三个双引号创建的多行字符串内容是:
这是三个双引号创建的
多行字符串!
str() 函数创建的字符串内容是:[1, 2, 3]
下标在 Python 中是一个编号,字符串、列表、元组都可以用下标来索引,我们可以通过下标来找到其对应的元素
。注意:下标是从 0 开始编号的,用0-(n-1)索引
。假如我们有一个字符串 s = 'abcd'
,现在我想得到这个字符串的第 1 个元素,那么我们可以通过 s[0]
得到第 1 个元素。此外 Python 还支持负数索引,用(-n)-(-1)
来索引。s[-1]
表示倒数第 1 个元素。测试如下:
In [1]: s = 'abcd'
In [2]: s[0]
Out[2]: 'a'
In [3]: s[-1]
Out[3]: 'd'
切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作。切片操作是一个浅拷贝操作,它只拷贝第一层对象。关于深拷贝和浅拷贝,留作以后探讨。切片的语法规则是:[开始:结束:步长]
,注意以下几点:
s = '0123'
,s[0:3]
截取的是s[0], s[1], s[2]
,截取不到 s[3]
,即取前不取后。测试如下:
In [1]: s = '0123456789'
In [2]: s[0:3]
Out[2]: '012'
In [3]: s[-3:-1]
Out[3]: '78'
In [4]: s[0:10:2]
Out[4]: '02468'
我们可以对字符串进行很多操作,比如首字母大写、查找、替换、拼接等等。在 Python 中内置了很多字符串操作的方法,我们可以通过 dir(str)
查看字符串的内置方法,在通过 help(str.function)
查看该方法的用法。或者直接打开下载的 Python 官方文档检索查看 str
对象的方法。
这里主要列几个用的比较多的方法。
str.split(sep=None, maxsplit=-1)
方法常用来把字符串转化为列表(list),它将字符串 str
以 sep
为分隔符,以 maxsplit
为分割次数,转化为列表。测试如下:
In [18]: s = 'Python is a great language!'
In [19]: s.split(' ')
Out[19]: ['Python', 'is', 'a', 'great', 'language!']
In [20]: s.split(' ', 1)
Out[20]: ['Python', 'is a great language!']
In [21]: s.split()
Out[21]: ['Python', 'is', 'a', 'great', 'language!']
str.join(iterable)
方法常用来把列表(list)转化为字符串,是一种常用高效的字符串拼接方法,它的含义是用 str
去拼接iterable
中的每个元素。这里需要注意:iterable 的每个元素必须都是字符串类型,否则会报 TypeError
。测试如下:
my_list = ['Python', 'is', 'great!']
result = ' '.join(my_list) # 用空格连接 my_list 中的各个元素
print(result)
输出结果:
Python is great!
如果将 my_list
更改为 my_list = ['Python', 'is', 'great!', 3]
,那么程序会报错,TypeError: sequence item 3: expected str instance, int found
。因为 3
是 int
类型。
此外还可以通过 +
实现字符串拼接功能。在字符串中,我们可以用 +
和 *
来增加字符串。其中 +
是拼接字符串,*
是重复字符串。测试如下:
name_info = '我的名字是Jock,'
age_info = '年龄是25岁!'
my_info = name_info + age_info # 这里加号把两个字符串拼接在一起
print(f'name_info + age_info 结果是:{my_info}')
s = 'abc'
s *= 3 # 等价于 s = s * 3,即把 'abc' 重复 3 次
print(s)
输出结果:
name_info + age_info 结果是:我的名字是Jock,年龄是25岁!
abcabcabc
str.replace(old, new[, count])
方法是实现将字符串 str
中所有的old
字符片段替换为 new
片段,如果给出了 count
参数,则只替换 count
次。测试如下:
In [11]: s = 'abcdabcdabcd'
In [12]: s.replace('a', 'f', 1)
Out[12]: 'fbcdabcdabcd'
In [13]: s.replace('a', 'f')
Out[13]: 'fbcdfbcdfbcd'
str.strip([chars])
方法常用来处理字符串的边界,比如去除字符串两端的空格等,它将字符串 str 两侧 [chars]
列表中出现的字符都去除,如果省略 [chars] 则默认去除字符串 str 两侧的空格。测试如下:
In [22]: ' Python '.strip()
Out[22]: 'Python'
In [23]: 'www.example.com'.strip('cmowz.')
Out[23]: 'example
列表(list)是 Python 中非常重要且常用的数据类型。在 Python 中 list 是一个可变序列。这里的可变是指 list 的元素个数可以增加或减少。列表用 []
包围,每个元素用 ,
分隔。
list 非常强大,我们可以把 list 当做一个大容器,什么都可以往里面装,比如:字符串、字典、列表、元组等。此外列表也支持下标和切片操作,非常灵活强大。
我们可以通过以下几种方式创建一个列表。
list_a = []
,创建一个空列表,推荐使用。list_b = list()
,使用 list() 函数创建一个空列表。list_c = [x for x in range(10)]
,使用列表推导式创建一个列表。往列表中增加元素主要有以下几种方法:
list.append(x)
:将元素 x 添加到 list 尾部,等价于 list[len(list):len(list)] = [x])
list.extend(list_b)
:将 list_b 中所有的元素添加到 list 中,等价于 list += list_b
list.insert(i, x)
:在 list 下标为 i 的位置插入 x,等价于 list[i:i] = [x]
+
:列表也可以直接拼接 list_a += list_b测试如下:
list_a = [1, 2]
list_a.append(3)
print(f'list_a = [1, 2],list_a.append(3) 是:{list_a}')
list_b, list_c = [1, 2, 3], [4, 5, 6]
list_b.extend(list_c)
print(f'list_b = [1, 2, 3],list_c = [4, 5, 6], list_b.extend(list_c) 是:{list_b}')
list_d = [1, 2, 3]
list_d.insert(0, 5)
print(f'list_d = [1, 2, 3],list_d.insert(0, 5) 是:{list_d}')
list_e, list_f = [1, 2, 3], [4, 5, 6]
print(f'list_e = [1, 2, 3],list_f = [4, 5, 6], list_e + list_f 是:{list_e + list_f}'')
结果如下:
list_a = [1, 2],list_a.append(3) 是:[1, 2, 3]
list_b = [1, 2, 3],list_c = [4, 5, 6], list_b.extend(list_c) 是:[1, 2, 3, 4, 5, 6]
list_d = [1, 2, 3],list_d.insert(0, 5)是:[5, 1, 2, 3]
list_e = [1, 2, 3],list_f = [4, 5, 6], list_e + list_f 是:[1, 2, 3, 4, 5, 6]
这里提一下,append()、extend()、insert() 方法都是在原有的 list 上添加,不会开辟新的内存空间,而用 +
会开辟新的内存空间,增加开销。应该根据具体需求灵活进行选择。
删除列表元素主要有以下方法:
修改列表元素值的主要是通过下标来确定要修改的是哪个元素,然后才能修改。格式: list[index] = value
将 list[index] 的值修改为 value。测试如下:
In [37]: list_a = [1, 2, 3]
In [38]: list_a[0] = 4
In [39]: list_a
Out[39]: [4, 2, 3]
查询列表元素的值有以下几种方法:
列表可以通过下标索引,它是一个有序序列,所以我们可以对列表进行排序。排序的方法有以下两种:
在 Python 中所有可变数据结构都遵循一个设计原则:原地修改可变对象是没有返回值的,或者说返回值是 None。比如 list 中的 sort、insert、remove 方法等。
列表可以作为栈(stack)使用,可以快速的实现(LIFO)后进先出,通过 pop() 和 append() 方法即可。用法如下:
>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]
同时列表也可以做队列(queue)使用,实现(FIFO)先进先出,通过 pop(0) 和 append() 方法实现。但是由于列表在末尾添加和删除一个元素是非常快的,但是在开头添加和删除一个元素速度比较慢,因为在列表的抬头添加或删除一个元素,都需要移动后面的所有元素。
这时候我们可以使用 collections.deque,它可以实现在开头和结尾都快速的删除和添加一个元素。用法如下:
>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry") # Terry arrives
>>> queue.append("Graham") # Graham arrives
>>> queue.popleft() # The first to arrive now leaves
'Eric'
>>> queue.popleft() # The second to arrive now leaves
'John'
>>> queue # Remaining queue in order of arrival
deque(['Michael', 'Terry', 'Graham'])
元组(tuple)是 Python 中一种不可变的序列。因为元组是不变的序列
,所以我们不可以对元组进行修改。元组用 ()
包围,每个元素用 ,
分隔,只有一个元素时,也要有一个 ,
。
为什么有了列表,还要设计一个不可变的元组呢?因为可变,虽然灵活,但是存在风险,所以元组不可变,代码相对更加安全。
元组可以认为是一种特殊的列表,除了会改变自身的方法不通用之外,其他的通用。比如列表中的 append()、extend()、insert()等方法不能用于元组。
创建一个元组我们有以下几个方法:
元组其实也是可以”改变“的。元组中的元素是不可以改变的,但是如果元组中的元素是可变对象,比如 list 的话,那么这时候这个可变对象是可以改变的。看下面的例子:
In [56]: t = (1, 2, 3)
In [57]: t[0] = 5
这里会报错:
TypeError: 'tuple' object does not support item assignment
In [58]: t = (1, [0, 1], 3)
In [59]: t[1][0] = 6
In [60]: t
Out[60]: (1, [6, 1], 3)
通过上面的例子我们可以发现,其实元组也是可以“改变”的,我们可以这样理解,上面这个例子中,t = (1, [0, 1], 3)
,元组 t 中的第二个元素其实是指向了列表[0, 1]的地址,列表[0, 1] 的地址没有改变,但是该地址的内存空间存储的值可以改变。
Python 中集合(set)是一个无序、可哈希的集合。集合具有确定性、互异性、无序性。创建集合的意义:
我们可以通过 s = set()
创建一个空集合,注意:s = {}
创建的是一个空字典。
更多 set 的用法可以用查看官方文档。
字典(dictionary)是 Python 中另一种极为重要的数据类型,是 Python 中唯一一个映射容器,用途非常广泛。字典也是可变的。字典是用{}
包围的,专门存储 key: value
,即键值对的容器,各键值对用逗号分隔。
它不同于列表和元组等序列通过下标来索引,字典是通过键(key)来索引的。
字典中键必须是不可变的:
数字
和 字符串
来作为字典的键。创建字典可以通过以下方式创建:
测试如下:
In [62]: a = dict(one=1, two=2, three=3)
In [63]: b = {'one': 1, 'two': 2, 'three': 3}
In [64]: c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
In [65]: d = dict([('two', 2), ('one', 1), ('three', 3)])
In [66]: e = dict({'three': 3, 'one': 1, 'two': 2})
In [67]: a == b == c == d == e
Out[67]: True
往字典中添加元素,我们有以下几种方法:
d[key] = value
:用这个操作来往字典中添加元素存在风险,可能会使得我有的 key-value 被更改,所以用这个方法前要用 key in d 进行键的判断。删除字典元素有以下几种方法:
我们可以通过 d[key] = value
来修改字典元素,如果 key 不存在,则会往字典中添加 key-value 键值对。
查询字典中的元素我们有以下几种方法:
示例如下:
d = {"one": 1, "two": 2, "three": 3, "four": 4}
print('遍历字典的key')
for key in d:
print(key)
print('遍历字典的value')
for value in d.values():
print(value)
print('遍历字典的item')
for item in d.items():
print(item)
print('遍历字典的key-value')
for key, value in d.items():
print(key, value)
结果输出:
遍历字典的key
one
two
three
four
遍历字典的value
1
2
3
4
遍历字典的item
('one', 1)
('two', 2)
('three', 3)
('four', 4)
遍历字典的key-value
one 1
two 2
three 3
four 4
for 循环的用法,我们下次学习会总结。这部分中字符串、列表、字典非常重要,它们的方法也很多,很难全部记住。如果忘记了我们及时查看官方文档的用法即可,不一定非要死记硬背。
学习这部分之后我们需要:
推荐阅读: