Skip to content

Python教程 - 5 容器(1)

什么是容器?

容器就是可以存储多个数据的一种数据类型,容器内的每一个数据称之为元素,其中的元素可以是任意类型的数据,包括字符串、数字、布尔,甚至是容器等等。

例如有一个班级,有40个学生,我们肯定不能定义40个变量来存储学生的信息,有1000个人,那不要命了,我们可以将所有学生的信息放到容器中。

容器分为5类:

  • 列表(list)
  • 字符串(str)
  • 元组(tuple)
  • 集合(set)
  • 字典(dict)

不同的容器有不同的特点,例如:

  • 是否支持重复的元素,有的容器中的元素不能重复,有的可以。
  • 是否可以修改
  • 是否有序

下面一一介绍。

5.1 列表(list)

列表就是一个普通的容器,满足你最原始的想象,主要有如下特点:

  • 列表中的元素可以重复
  • 列表中的元素可以修改,可以增加、修改、删除
  • 列表中的元素是有序的,可以通过索引来访问
  • 列表中可以存储不同数据类型的数据
  • 列表中最多可以容纳 2^63 - 1个元素,这辈子够你用了。

5.1.1 列表的定义

列表使用 方括号[] 定义,列表内每个元素使用 逗号, 分隔。

python
# 定义一个列表,并赋值给一个变量
变量名称 = [元素1, 元素2, 元素3, ...]

# 定义空列表
变量名称 = []				# 方式1
变量名称 = list()		# 方式2

举个栗子:

定义一个列表,其中存储 4 个人的名字:

python
item_list = ["zhangsan", 18, 3.14, True]			# 定义一个容器

print(item_list)				# 打印容器
print(type(item_list))	# 打印容器类型

执行结果:

['zhangsan', 18, 3.14, True]
<class 'list'>

可以看到列表可以存储多个数据,并且可以存储不同类型的数据。

打印列表会显示列表中所有的元素,打印列表类型可以看到列表的类型为list。

5.1.2 列表的索引

我们已经将数据存储到列表中了,那么如何获取列表中的元素呢?

可以通过元素的索引(也称之为下标)来取出指定位置的元素。

如上图,列表中的每个元素,都有一个索引,从0开始,依次递增。

只需要按照下标索引,就可以获取对应的元素。

举个栗子:

python
name_list = ["zhangsan", "lisi", "wangwu", "zhaoliu", "qianqi", "chenba"]			# 定义一个容器
print(name_list[0])
print(name_list[3])

执行结果:

zhangsan
zhaoliu

注意,在访问列表元素的时候,下标不能越界,例如上面的列表,索引最大是5,超过5就会出现下标越界的错误。

列表索引的访问,除了可以从0开始递增访问,还可以反向访问,如下图:

列表可以从后向前访问,从-1开始,依次递减。

举个栗子:

python
name_list = ["zhangsan", "lisi", "wangwu", "zhaoliu", "qianqi", "chenba"]			# 定义一个容器
print(name_list[-1])
print(name_list[-3])

执行结果:

chenba
zhaoliu

5.1.3 容器的嵌套

我们一开始说了,容器中可以存储任意类型的数据,包括容器类型。

所以容器是可以嵌套使用的,包括后面的元组(tuple)、集合(set)、字典(dict),可是相互嵌套使用。

举个栗子:

python
item_list = ["zhangsan", 18, 3.14, True, [1, 2, 3]]

上面的列表中还包含了一个列表,也可以和后面的容器相互嵌套。

访问嵌套的列表,可以继续使用它下标来访问:

python
item_list = ["zhangsan", 18, 3.14, True, [1, 2, 3]]
print(item_list[-1][1])

item_list[-1] 得到的是[1, 2, 3] ,继续使用 item_list[-1][1],获取到的是其中的元素 2 。

5.1.4 列表常用操作

常用的操作有很多,例如列表中元素的插入、删除、清空、修改等。

1 列表长度

可以使用 len() 函数求列表或其他容器,包括字符串的长度。

这个是Python的内置函数。

举个栗子:

python
name_list = ["zhangsan", "lisi", "wangwu", "zhaoliu", "qianqi", "chenba"]			# 定义一个容器
print(len(name_list))

str = "埋骨何须桑梓地,人生何处不青山"
print(len(str))

执行结果:

6
15

所以获取列表的最后一个元素,可以使用 list[-1] 或 list[len(list) - 1] 。

2 查找元素

可以使用 列表.index() 方法查找元素在列表中的下标,如果找不到,会报错。

方法是通过对象来调用的 对象.方法(参数),和函数略有不同。

举个栗子:

python
int_list = [1, 2, 3, 1]
print(int_list.index(1))					# 查找1的位置
print(int_list.index(1, 1))				# 查找的时候,可以执行起始位置
print(int_list.index(1, 1, 6))		# 查找的时候,可以指定起始、结束位置
print(int_list(4))								# 找不到程序会报错

执行结果:

0
3
3
Traceback (most recent call last):
File "***/hello_world.py", line 5, in <module>;
 print(int_list(4))
       ^^^^^^^^^^^
TypeError: 'list' object is not callable

注意,只会返回找到的第一个位置。

查找的时候,可以指定查找的起始位置和结束位置,起始位置和结束位置的index可以超过数组的长度,没有越界问题。

找不到程序就会报错,程序就不能继续执行了,这不是坑爹吗?

不急,后面会学习异常捕获,再学习如何处理。

3 修改元素

修改元素,直接通过下标获取元素,直接重新赋值就可以了。

举个栗子:

python
int_list = [1, 2, 3, 1]
int_list[-1] = 4
print(int_list)

执行结果:

[1, 2, 3, 4]

注意,访问列表的时候,不要让下标越界。

4 插入元素

使用 列表.insert(下标, 元素) 方法,可以在指定下标位置,插入元素。

举个栗子:

python
int_list = [1, 2, 3, 1]
int_list.insert(3, 4)			# 在下标3的位置插入元素4
int_list.insert(8, 5)			# 在下标8的位置插入元素5,不会存在越界问题
print(int_list)

执行结果:

[1, 2, 3, 4, 1, 5]

插入时,指定的下标,不会存在越界问题。

5 追加元素

使用 列表.append(元素) 方法,可以在列表的末尾追加元素。

举个栗子:

python
int_list = [1, 2, 3, 1]
int_list.append(5)							# 追加元素
print(int_list)

执行结果:

[1, 2, 3, 1, 5]

还可以使用 列表.extend(容器) 方法,将其他容器(列表、元组、集合)中的元素,依次追加到列表末尾。

python
int_list = [1, 2, 3, 1]
int_list.extend([5, 6, 7])				# 追加容器中所有元素
print(int_list)

执行结果:

[1, 2, 3, 1, 5, 6, 7]

6 删除元素

删除元素有两种方式:一种是根据索引删除,一种是根据内容删除。

根据索引删除

根据索引删除又有两种方法:

方法一:del 列表[下标]

方法二:列表.pop(下标)

举个栗子:

python
int_list = [1, 2, 3, 1]
del int_list[-1]        # 删除最右一个元素
int_list.pop(1)         # 删除第二个元素
print(int_list)

执行结果:

[1, 3]

注意,删除的时候,列表下标不要越界,否则报错。

根据内容删除

根据内容删除,使用 .remove() 方法,该方法会从前向后检索,删除列表中第一个匹配的元素。

python
int_list = [1, 2, 3, 1]
int_list.remove(1)
print(int_list)

执行结果:

[2, 3, 1]

7 清空列表

可以使用 列表.clear() 方法,清空列表中的所有元素。

举个栗子:

python
int_list = [1, 2, 3, 1]
int_list.clear()					# 清空列表中所有的元素
print(int_list)

执行结果:

[]

8 统计指定元素的数量

可以使用 列表.count(元素) 方法 ,来统计列表内,指定元素的数量。

举个栗子:

python
int_list = [1, 2, 3, 1]
print(int_list.count(1))				# 统计列表中值为1的元素的数量

执行结果:

2

9 列表的遍历

容器中存储的是多个元素,所以经常需要遍历容器,依次取出容器里的元素,对其进行处理。

而对于列表,遍历的方式主要有两种:

  • for循环遍历
  • while循环变量
for循环遍历

语法:

python
for 元素 in 容器:
    # 对元素进行处理

举个栗子:

python
int_list = [1, 2, 3, 4]
for item in int_list:				# 临时变量名称自定义
    print(item)

执行结果:

1
2
3
4
while 循环遍历

语法:

python
index = 0										
while index < len(列表):
    元素 = 列表[index]

    # 对元素进行处理
    
    index += 1

举个栗子:

python
int_list = [1, 2, 3, 4]

index = 0
while index < len(int_list):
    item = int_list[index]				# 使用下标获取元素

    print(item)
    index += 1

执行结果:

1
2
3
4

for循环和while循环的区别:

while循环没有for循环简洁,但是while循环更灵活,可以根据条件,自行控制取出的元素,例如可以控制只遍历 index 为偶数位的元素,index += 2即可。for循环只能一个一个遍历元素,次数也是固定的。

10 遍历与删除

现在有个列表 [8, 20, 15, 5],现在想删除容器内大于10的元素。

于是,又要哐哐敲代码了:

python
num_list = [8, 20, 15, 5]

for num in num_list:
    if num > 10:
        num_list.remove(num)

print(num_list)

执行结果:

[8, 15, 5]

代码没问题啊,What the f**k,为什么呢?

其实遍历列表,底层还是通过下标来操作数据的,通过下标递增,来实现数据读取,当下标为1的时候,读取到20的时候,20 > 10,将20删掉了,那么后面的元素会向前移动,此时这一次的循环结束,下标加1,此时下标变成了2,而此时num_list[0] = 8,num_list[1] = 15,num_list[2] = 5,所以直接读取到5的,跳过了15。


那怎么在遍历的时候删除呢?可以采用倒序遍历。

从列表的最后一个元素开始遍历,这样删除元素不会影响未遍历的元素的索引。

python
num_list = [8, 20, 15, 5]

# 从最后一个开始向前遍历,步进为-1
for i in range(len(num_list) - 1, -1, -1):
    if num_list[i] > 10:
        num_list.pop(i)

print(num_list)

11 列表推导式

什么是列表推导式?

就是使用一种更简洁的方式,将可迭代对象转换为列表。

举个例子:

我想将一个列表中的数字都乘以10。于是写代码如下:

python
int_list = [1, 2, 3, 4]
int_list2 = []
for item in int_list:
    int_list2.append(item * 10)
print(int_list2)

可以使用列表推导式,让代码更简洁,语法如下:

python
变量 = [表达式 for 变量 in 可迭代对象]
变量 = [表达式 for 变量 in 可迭代对象 if 条件]

所以上面的代码可以改写成如下:

python
int_list = [1, 2, 3, 4]
int_list2 = [item * 10 for item in int_list]
print(int_list2)

如果只想偶数,则还可以添加条件判断:

python
int_list = [1, 2, 3, 4]
int_list2 = [item * 10 for item in int_list if item % 2 == 0]
print(int_list2)

执行结果:

[20, 40]

列表推导式用的不多,会让代码可读性变差,但是需要知道这种写法。

12 将列表拼接成字符串

可以使用 连接符.join(列表) 方法,可以将列表拼接成一个字符串。

举个栗子:

python
int_list = ["a", "b", "c", "d"]
str = "-".join(int_list)				# 使用-将列表中的元素拼接起来。
print(str)

执行结果:

a-b-c-d

13 将字符串分割成列表

可以使用分割符,将字符串分割成列表。

举个栗子:

python
str = "I love python"
str_list = str.split(" ")        # 使用空格将字符串分割成一个列表
print(str_list)

执行结果:

['I', 'love', 'python']

5.2 元组(tuple)

什么是元组?

元组和列表非常相似,和列表的区别就是:列表的元素可以被修改,元组在定义的时候就确定了元素,后面是不可以修改的。

如果我们要封装数据,又不希望数据被修改,就可以使用元组了。

1 元组的定义

元组使用 **小括号() **来定义,元组中的元素使用 逗号, 分隔。

python
# 定义一个列表,并赋值给一个变量
变量名称 = (元素1, 元素2, 元素3, ...)

# 定义一个元素的元组
变量名称 = (元素1, )

# 定义空列表
变量名称 = ()				# 方式1
变量名称 = tuple()		# 方式2

注意:定义包含一个元素的元组,后面必须带一个逗号。

因为元组中的元素是不能修改的,所以创建一个空元组好像也没有什么用,因为不能增加和删除元素。

2 元组的修改

因为元组中的元素是不能修改的,修改会报错。

python
int_tuple = (1, 2, 3)
int_tuple[0] = 5

执行结果:

Traceback (most recent call last):
File "****/hello_world.py", line 2, in <module>
int_tuple[0] = 5

TypeError: 'tuple' object does not support item assignment

再看下面的情况

python
int_list = [4, 5, 6]
int_tuple = (1, 2, 3, int_list)

print(int_tuple)
int_list.append(7)							# 修改元组中类型为列表的元素
print(int_tuple)

执行结果:

(1, 2, 3, [4, 5, 6])
(1, 2, 3, [4, 5, 6, 7])

不是说元组的元素不能修改吗,为什么现在又可以修改了。

其实元组中第4个元素始终指向的是列表的地址,没有变,只是列表中的元素变了,参见 4.6 容器的内存。

3 元组常用操作

元组元素不能修改,所以操作的方法比较少。

python
int_tuple = (1, 2, 3, 1)

print("获取元素:%d" % int_tuple[2])             				# 根据下表获取元素

print("获取元素2的位置:%d" % int_tuple.index(2))       	# 获取元素2的位置

print("元素1的个数:%d" % int_tuple.count(1))							# 获取元素1的个数

print("元组的长度:%d" % len(int_tuple))       						# 获取元组长度

元组的嵌套、遍历等操作都和列表相同,可以参照列表。

元组赋值给多个变量

可以将元组直接赋值给多个变量。

python
my_tuple = (1, 2)
a, b = my_tuple
print(a)
print(b)

执行结果:

1
2

需要注意,元组元素的个数需要和赋值的变量的个数相同,否则会报错。

5.3 字符串(Str)

前面已经讲解了字符串的很多知识,没想到我又来了。更没想到,字符串也是容器吧。

字符串是字符的容器,一个字符串可以存放任意数量的字符。

和列表一样,字符串也可以通过下标来访问其中的元素。

和元组一样,字符串中的元素不可以修改。

python
str = "Hello"
print(str[0])
print(str[-1])

执行结果:

H
o

和元组一样,字符串也是一个无法修改的容器,所以不能修改其中的字符,也不能移除和追加字符。

1 字符串长度

len() 函数可以获取字符串的长度。

举个栗子:

python
str = "Good good study, day day up"
print(len(str))

执行结果:

27

2 查找元素

和列表一样,使用 index() 方法查找字符在字符串中的下标。

python
str = "Good good study, day day up"
print(str.index("study"))

执行结果:

10

3 字符串替换

我们可以通过 replace() 方法替换字符串中的字符。

语法: 字符串.replace(字符串1, 字符串2) ,将字符串中全部的字符串1替换为字符串2

注意,替换完成,返回的是一个新的字符,旧的字符串是不变的,因为字符串是不可变的。

python
str = "Good good study, day day up"
new_str = str.replace("study", "play")
print(new_str)
print(str)

执行结果:

Good good play, day day up
Good good study, day day up

4 字符串分割

可以使用 split() 方法,通过指定字符分割字符串。

语法:字符串.split(分割符字符串),使用分割字符串讲字符串分割成多个字符串。

注意,字符串本身不变,得到的结果是一个字符串列表。

python
str = "Good good study, day day up"
str_list = str.split(" ")
print(str_list)
print(type(str_list))

执行结果:

['Good', 'good', 'study,', 'day', 'day', 'up']
<class 'list'>

5 规整操作

用户在登录系统的时候,输入用户名,用户名前后可能不小心输入了空格,我们在处理的时候,需要处理掉字符串前后的空格。

我们可以使用 strip() 方法对字符串进行规整。

举个栗子:

python
str = "   zhangsan   "
new_str = str.strip()  # 调用 strip() 方法去除首尾空格
print(new_str)

执行结果:

zhangsan

strip() 方法还可以接收参数,去掉前后指定的字符串。

举个栗子:

python
str = "123zhangsan321"
new_str = str.strip("12")  # 移除首尾的 '1' 和 '2'
print(new_str)

str = "123zhangsan132"
new_str = str.strip("21")   # 移除首尾的 '1' 和 '2'
print(new_str)

str = "123zhangsan321"
new_str = str.strip("23")   # 移除首尾的 '2 和 '3',结尾遇到的是1,不移除
print(new_str)
  • strip("12") 的作用:从字符串开头和结尾开始检查,移除所有在 "12" 中的字符(即 '1''2'),直到遇到第一个不在 "12" 中的字符

执行结果:

3zhangsan3
3zhangsan13
123zhangsan321

可以看到,参数是分开匹配的,当字符串最前或最后的一个字符在指定的参数中后,会继续匹配前后的下一个字符。

6 统计指定字符出现的数量

可以使用 字符串.count(元素) 方法 ,来统计字符串内,指定子串出现的数量。

举个栗子:

python
str = "Good good study, day day up"
print(str.count("day"))

执行结果:

2

7 字符串的遍历

和列表一样,字符串也可以使用while或for循环对字符进行遍历。

while 循环

python
str = "Hello"
index = 0
while index < len(str):
    print(str[index])
    index += 1

for循环

python
str = "Hello"
for s in str:
    print(s)

执行结果:

H
e
l
l
o

8 字符串大小比较

"abc" 和 "+-X/" 哪个字符串大呢?

python
str1 = "abc"
str2 = "+-X/"
print(str1 > str2)

执行结果:

True

那么字符串是怎么比较大小的呢?

字符串中的字符:大小写英文字符、数字、特殊字符在ASCII码中都有对应的数值,在进行字符串比较的时候,会依次取出两个字符串的字符进行比较。例如先取出两个字符串的第一个字符进行比较,哪个字符大,哪个字符串就大,如果相等,则取第二个字符进行比较,依次类推,直到比出最后的结果。