Python 系列(十二) List 列表实战,搞定数据增删改查与批量处理
1 | 作者:李晓辉 |
- Python 系列(一) 从零开始认识 Python,入门其实没那么难
- Python 系列(二) 学 Python 的第一步,把开发环境搭建好
- Python 系列(三) 基础语法避坑指南,缩进、大小写、续行与注释
- Python 系列(四) Python 输入输出详解,print()、input() 与常见避坑指南
- Python 系列(五) 数值类型与运算符详解,整除、浮点精度与进制转换实战
- Python 系列(六) 字符串处理实战,查找、替换、切片与日志分析
- Python 系列(七) 类型转换详解,int()、float()、str() 与金额计算避坑
- Python 系列(八) Python 流程控制入门,掌握 if、elif 和 else
- Python 系列(九) Python 逻辑运算符详解,and、or、not 一篇搞懂
- Python 系列(十) while、for 循环实战,彻底搞懂 range、break 与 continue
- Python 系列(十一) list、tuple、set、dict,到底该怎么选?
- Python 系列(十二) List 列表实战,搞定数据增删改查与批量处理
- Python 系列(十三) Tuple 元组实战,搞懂不可变特性与 enumerate() 遍历
在上一篇文章中,我们认识了 Python 的四大内置集合类型:list、tuple、set 和 dict,了解了它们各自的特点和适用场景。
那么如何快速创建列表?如何通过索引和切片访问元素?如何动态添加、删除和修改数据?又该如何遍历列表,批量处理服务器巡检任务?
这篇文章,我们就从最常用的 list 入手,深入学习列表的创建、访问、切片、增删改、排序、解包和循环遍历。
还是以 Linux 运维工作为例,看看这些基础语法如何帮助我们编写更实用的自动化脚本。
从服务器清单认识 List
假设你是一名 Linux 运维工程师,需要每天检查公司的服务器运行状态。
刚开始,公司只有几台服务器,你可以直接登录服务器,执行 uptime、free -h 和 df -h,查看系统负载、内存和磁盘空间。
但是,随着业务发展,服务器数量从几台增加到几十台,甚至上百台。每天手动登录服务器进行检查,显然不太现实。
这时,我们就可以考虑使用 Python 编写一个巡检脚本,把需要检查的服务器保存起来,再通过循环逐台处理。
例如:
1 | #!/usr/bin/env python3 |
运行结果:
1 | ['web01', 'web02', 'db01', 'cache01'] |
这里的 servers 就是一个列表,也就是 list。
列表是一种有序、可变的序列,可以保存零个或多个对象。列表中的元素可以是字符串、整数、浮点数,甚至还可以是其他列表。
列表有两个非常重要的特点:
- 有序: 元素按照一定的顺序排列,可以通过索引访问,也支持切片操作。
- 可变: 创建列表之后,可以根据需要添加、删除或修改其中的元素。
此外,列表允许出现重复元素。
例如:
1 | servers = ["web01", "web02", "db01", "web01"] |
运行结果:
1 | ['web01', 'web02', 'db01', 'web01'] |
两个 web01 都被保留了下来。
因此,如果需要保存一组有顺序、允许重复、后续可能发生变化的数据,列表通常是一个很合适的选择。
创建列表
Python 提供了多种创建列表的方式。根据数据来源和实际需求,我们可以选择最合适的写法。
使用方括号创建列表
最常见的方式,就是使用一对方括号 [],将需要保存的元素放在其中,并使用逗号分隔。
1 | servers = ["web01", "web02", "db01"] |
运行结果:
1 | ['web01', 'web02', 'db01'] |
可以看到,列表中的元素不一定需要是同一种类型。
例如,我们可以将服务器名称、IP 地址和端口号放在同一个列表中:
1 | server_info = ["web01", "192.168.1.10", 22] |
运行结果:
1 | ['web01', '192.168.1.10', 22] |
虽然 Python 允许这样做,但在实际编写程序时,仍然应该根据数据的含义合理组织信息。如果需要保存具有明确字段关系的数据,后续还可以考虑使用元组或字典。
创建空列表
有时,我们暂时不知道列表中应该保存哪些数据,需要先创建一个空列表,等程序运行过程中再逐步添加元素。
这时可以使用两种方式:
1 | servers = [] |
运行结果:
1 | [] |
两种方式都可以创建空列表。
例如,我们可以先创建一个空的巡检结果列表,之后再把每台服务器的检查结果添加进去:
1 | check_results = [] |
运行结果:
1 | ['web01: OK', 'web02: OK', 'db01: WARNING'] |
这种写法在自动化脚本中非常常见:先准备一个容器,再随着程序执行逐步收集结果。
使用 list() 构造函数
除了直接使用方括号,我们还可以使用 list() 创建列表。
1 | servers = list(("web01", "web02", "db01")) |
运行结果:
1 | ['web01', 'web02', 'db01'] |
这里的 list() 接收了一个元组,并将其中的元素转换为列表。
它也可以将字符串转换为由单个字符组成的列表:
1 | letters = list("Linux") |
运行结果:
1 | ['L', 'i', 'n', 'u', 'x'] |
需要注意,list() 并不是简单地把任意对象放进列表,而是会从可迭代对象中逐个获取元素。
例如:
1 | numbers = list(range(1, 6)) |
运行结果:
1 | [1, 2, 3, 4, 5] |
这里的 range(1, 6) 生成从 1 到 5 的整数序列,再由 list() 将这些整数保存为列表。
后面学习循环时,我们还会经常用到 range()。
通过索引访问列表元素
列表创建完成后,接下来就需要访问其中的数据。
例如,巡检脚本需要知道第一台服务器的名称,或者获取最后一台服务器的名称。这时可以使用索引。
Python 列表的索引从 0 开始,而不是从 1 开始。
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | web01 |
对应关系如下:
| 索引 | 元素 |
|---|---|
0 | web01 |
1 | web02 |
2 | db01 |
3 | cache01 |
为什么索引从 0 开始?
这是 Python 等许多编程语言采用的索引规则。刚开始可能需要适应,但理解之后就很容易掌握。
使用负数索引
如果想访问列表最后一个元素,难道每次都要先计算列表的长度吗?
其实不需要。Python 支持负数索引,可以从列表末尾向前访问元素。
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | cache01 |
可以这样理解:
servers[0]:第一个元素。servers[1]:第二个元素。servers[-1]:最后一个元素。servers[-2]:倒数第二个元素。
在实际工作中,如果我们只关心最近一次巡检结果,或者需要获取列表末尾的数据,负数索引就很方便。
索引越界会发生什么?
假设列表中只有四台服务器:
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行时会出现错误:
1 | Traceback (most recent call last): |
为什么会报错?
因为列表的有效索引是 0 到 3,而不是 0 到 4。
在编写自动化脚本时,如果索引来自用户输入,或者来自动态计算的结果,就需要注意检查索引范围,避免程序因为访问不存在的位置而中断。
使用切片获取部分元素
索引可以获取单个元素,但如果我们希望一次取出多台服务器,该怎么办?
例如,有一个包含十台服务器的列表,现在只想获取前五台,或者获取其中的第二台到第四台。
这时就可以使用切片。
切片的基本语法是:
1 | list[start:stop:step] |
其中:
start:切片开始的位置,包含该位置。stop:切片结束的位置,但不包含该位置。step:每次跨过多少个位置,默认值为1。
先看一个简单的例子:
1 | servers = [ |
运行结果:
1 | ['web01', 'web02', 'web03'] |
第一个切片 servers[0:3] 从索引 0 开始,到索引 3 之前结束,因此取出前三个元素。
第二个切片 servers[2:5] 则取出索引 2、3 和 4 对应的元素。
这里有一个非常重要的规则:切片包含开始位置,但不包含结束位置。
记住这一点,后续使用切片就不容易出错。
省略切片的开始或结束位置
如果希望从列表开头一直取到指定位置,可以省略开始索引。
1 | servers = ["web01", "web02", "web03", "db01", "db02"] |
运行结果:
1 | ['web01', 'web02', 'web03'] |
如果希望从某个位置一直取到列表末尾,则可以省略结束索引。
1 | print(servers[2:]) |
运行结果:
1 | ['web03', 'db01', 'db02'] |
如果两个位置都省略:
1 | print(servers[:]) |
就会得到包含全部元素的一个新列表。
输出
1 | ['web01', 'web02', 'web03', 'db01', 'db02'] |
这在需要复制列表时也很常见,不过需要注意:这种切片操作创建的是浅拷贝。如果列表中包含其他可变对象,内部对象仍然可能被多个列表共同引用。
使用步长进行切片
切片还支持第三个参数 step,用于指定每次取元素时跨过多少个位置。
例如:
1 | numbers = [10, 20, 30, 40, 50, 60, 70, 80] |
运行结果:
1 | [10, 30, 50, 70] |
numbers[::2] 表示从头开始,每隔一个元素取一次。
numbers[1::2] 则从索引 1 开始,同样每隔一个元素取一次。
步长还可以是负数:
1 | numbers = [10, 20, 30, 40, 50] |
运行结果:
1 | [50, 40, 30, 20, 10] |
这是一种常见的列表反向取值方式。
需要注意,[::-1] 返回的是一个新列表,并不会直接修改原列表。
在运维场景中,切片可以用于拆分批次任务。例如,一次需要处理一百台服务器,但每批只希望处理十台,就可以使用切片按批次提取服务器清单。
列表的动态操作
列表最大的特点之一,就是创建之后仍然可以修改。
随着服务器数量变化,我们可能需要添加新的服务器、删除下线的服务器、修改已有信息,或者重新调整服务器的排列顺序。
Python 提供了多种列表操作方法。
使用 append() 添加元素
如果巡检范围增加了一台服务器,我们可以使用 append() 将它添加到列表末尾。
1 | servers = ["web01", "web02", "db01"] |
运行结果:
1 | ['web01', 'web02', 'db01', 'cache01'] |
append() 每次添加一个对象,并将这个对象作为一个整体放入列表。
例如:
1 | servers = ["web01", "web02"] |
运行结果:
1 | ['web01', 'web02', ['db01', 'cache01']] |
注意,最后一个元素本身是一个列表,而不是两个独立的服务器名称。
如果希望把另一个列表中的元素逐个添加进来,就应该使用 extend()。
使用 extend() 扩展列表
假设现有服务器清单保存在一个列表中,新增服务器则保存在另一个列表中。
1 | servers = ["web01", "web02"] |
运行结果:
1 | ['web01', 'web02', 'db01', 'cache01'] |
extend() 会遍历传入的可迭代对象,并把其中的元素逐个添加到原列表。
这与 append() 有明显区别:
1 | servers = ["web01", "web02"] |
结果是:
1 | ['web01', 'web02', ['db01', 'cache01']] |
如果把 append() 换成 extend(),结果就会变成一个包含四个字符串的列表。
因此可以记住:
append():添加一个对象。extend():把另一个可迭代对象中的元素逐个添加进来。
使用 insert() 在指定位置插入元素
有时,新服务器需要插入列表的指定位置,而不是直接追加到末尾。
例如:
1 | servers = ["web01", "db01", "cache01"] |
运行结果:
1 | ['web01', 'web02', 'db01', 'cache01'] |
insert(1, "web02") 表示将 web02 插入索引 1 的位置,原来位于该位置及之后的元素会向后移动。
在需要维护特定处理顺序的任务清单中,可以使用 insert() 将任务插入指定位置。
不过,如果经常在列表中间插入大量元素,可能会带来额外的移动开销。对于这类场景,应该根据实际需求选择合适的数据结构。
使用 pop() 删除元素
如果一台服务器已经下线,我们可能需要将它从巡检清单中移除。
pop() 可以删除并返回指定位置的元素。
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | 删除的服务器: db01 |
如果不指定索引,pop() 默认删除并返回最后一个元素。
1 | servers = ["web01", "web02", "db01"] |
运行结果:
1 | db01 |
需要注意,pop() 会直接修改原列表。如果列表为空,或者指定的索引不存在,就会引发 IndexError。
使用 remove() 删除指定元素
如果我们知道需要删除的服务器名称,也可以使用 remove()。
1 | servers = ["web01", "web02", "db01", "web02"] |
运行结果:
1 | ['web01', 'db01', 'web02'] |
这里需要特别注意:如果列表中存在多个相同元素,remove() 只会删除第一个匹配的元素。
如果列表中不存在指定元素,则会引发 ValueError。
因此,在删除元素之前,如果不能确定目标一定存在,可以先进行成员测试:
1 | if "web02" in servers: |
这种写法能够避免因为目标元素不存在而直接报错。
使用 del 删除元素或切片
除了 pop() 和 remove(),Python 还提供了 del 语句。
例如:
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | ['web01', 'db01', 'cache01'] |
del servers[1] 删除索引 1 对应的元素。
如果希望删除一段范围,也可以使用切片:
1 | servers = ["web01", "web02", "web03", "db01", "db02"] |
运行结果:
1 | ['web01', 'db01', 'db02'] |
这里删除的是索引 1 和 2 对应的元素,不包含结束索引 3。
如果希望清空列表中的所有元素,还可以使用 clear():
1 | servers = ["web01", "web02", "db01"] |
运行结果:
1 | [] |
需要区分的是,clear() 会清空原列表,而 del servers 则会删除变量 servers 这个名称的绑定。两者并不是一回事。
修改列表中的元素
列表不仅可以增删元素,还可以通过索引直接修改指定位置的值。
1 | servers = ["web01", "web02", "db01"] |
运行结果:
1 | ['web01', 'web03', 'db01'] |
原来的 web02 被替换成了 web03。
也可以通过切片一次修改多个元素:
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | ['web01', 'web03', 'db02', 'cache01'] |
切片赋值可以替换一段元素,甚至可以改变列表长度。因此,使用时需要特别注意切片范围和替换内容。
列表的查找与判断
在巡检脚本中,我们经常需要判断某台服务器是否存在于当前清单中,或者查找某个元素所在的位置。
Python 提供了 in、not in、index() 和 count() 等常用操作。
使用 in 判断元素是否存在
例如,我们希望在执行巡检之前,先确认某台服务器是否已经被添加到清单中。
1 | servers = ["web01", "web02", "db01"] |
运行结果:
1 | True |
in 用于判断元素是否存在于列表中,not in 则用于判断元素是否不存在。
这类判断通常会返回布尔值,也就是 True 或 False。
例如:
1 | if "web01" in servers: |
在实际脚本中,可以根据判断结果决定是否执行后续操作。
使用 index() 查找元素位置
如果不仅需要判断元素是否存在,还希望知道它位于哪个位置,可以使用 index()。
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | 2 |
因为 db01 位于索引 2 的位置。
如果列表中存在重复元素,index() 默认返回第一个匹配元素的索引。
如果目标元素不存在,则会引发 ValueError,因此需要根据实际情况判断是否应该先检查元素是否存在。
使用 count() 统计元素出现次数
如果我们怀疑服务器清单中存在重复数据,可以使用 count() 统计某个元素出现了多少次。
1 | servers = ["web01", "web02", "db01", "web01"] |
运行结果:
1 | 2 |
这里,web01 出现了两次,而 db01 只出现了一次。
count() 适合统计指定元素在列表中的出现次数,但如果需要处理大量数据并频繁统计不同元素的数量,就应该考虑其他更合适的数据组织方式,例如字典或集合。
列表的反转与排序
服务器清单有时需要按照特定顺序排列。例如,按照名称排序,或者将处理顺序反转。
Python 提供了 reverse() 和 sort() 两种常用方法。
使用 reverse() 反转列表
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | ['cache01', 'db01', 'web02', 'web01'] |
reverse() 会直接修改原列表,将元素的排列顺序反转。
需要注意,它并不是按照字母顺序重新排序,而只是将现有顺序倒过来。
如果原列表是:
1 | ['web03', 'web01', 'web02'] |
反转后就会变成:
1 | ['web02', 'web01', 'web03'] |
它不会自动变成按名称升序排列的结果。
使用 sort() 排序列表
如果希望按照服务器名称排序,可以使用 sort()。
1 | servers = ["web03", "web01", "web02", "db01"] |
运行结果:
1 | ['db01', 'web01', 'web02', 'web03'] |
默认情况下,字符串按照字典序进行比较,整数则按照数值大小进行排序。
例如:
1 | numbers = [10, 20, 3, 100, 5] |
运行结果:
1 | [3, 5, 10, 20, 100] |
如果希望按照降序排列,可以使用 reverse=True:
1 | numbers = [10, 20, 3, 100, 5] |
运行结果:
1 | [100, 20, 10, 5, 3] |
使用 sorted() 保留原列表
除了 sort(),Python 还提供了内置函数 sorted()。
两者的区别在于:
sort():直接修改原列表。sorted():返回一个新的排序结果,不会直接修改原列表。
例如:
1 | servers = ["web03", "web01", "web02"] |
运行结果:
1 | 原列表: ['web03', 'web01', 'web02'] |
如果后续还需要保留原始顺序,使用 sorted() 会更加方便。
还有一个容易踩的坑:sort() 和 reverse() 都是直接修改列表的方法,调用它们不会返回排序后的列表或反转后的列表。
例如,下面的写法是不正确的:
1 | servers = ["web03", "web01", "web02"] |
输出结果是:
1 | None |
这是因为 sort() 的返回值是 None,而不是排序后的列表。
正确的写法应该是:
1 | servers = ["web03", "web01", "web02"] |
输出
1 | ['web01', 'web02', 'web03'] |
列表解包:把元素分配给不同变量
前面我们通过索引访问列表元素。
例如:
1 | server_info = ["web01", "192.168.1.10", 22] |
输出
1 | web01 192.168.1.10 22 |
这种方式没有问题,但如果列表中保存的元素数量比较固定,而且每个元素都有明确的含义,就可以使用解包,让代码更简洁。
1 | server_info = ["web01", "192.168.1.10", 22] |
运行结果:
1 | web01 |
这就是列表解包。
Python 会按照位置,将列表中的元素依次赋值给对应的变量。
需要注意,普通解包要求变量数量与元素数量一致。
例如:
1 | servers = ["web01", "web02", "db01"] |
这段代码会引发 ValueError,因为列表有三个元素,但左侧只有两个变量。
1 | Traceback (most recent call last): |
如果只希望取出部分元素,也可以使用带星号的解包语法:
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | web01 |
其中,first 接收第一个元素,others 则接收剩余元素,并且仍然是一个列表。
解包常用于处理字段数量固定的数据,例如服务器地址与端口、命令执行结果中的多个返回值等。不过,如果数据具有明确的字段名称,而且字段较多,字典往往更容易维护。
使用 for 循环遍历列表
列表最常见的用途之一,就是保存一组需要依次处理的数据。
在 Linux 运维自动化中,我们可能需要逐台检查服务器,或者逐个处理日志文件。
这时就可以使用 for 循环遍历列表。
直接遍历元素
例如:
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | web01 |
这里的 for server in servers 表示依次从 servers 中取出元素,并将当前元素赋值给变量 server。
每次循环,server 都会指向当前处理的服务器名称。
这种方式简单直观,也是 Python 中推荐优先使用的遍历方式之一。
例如,我们可以用类似的结构组织巡检任务:
1 | servers = ["web01", "web02", "db01"] |
运行结果:
1 | 正在检查服务器:web01 |
这里还没有真正连接服务器,但循环结构已经具备了批量处理任务的基本形式。后续学习 SSH 自动化或调用 API 时,就可以在循环内部执行实际的检查逻辑。
使用索引遍历列表
如果除了元素本身,还需要知道它在列表中的位置,也可以使用索引进行遍历。
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | 0 web01 |
这里涉及两个常见的内置函数:
len(servers):返回列表的元素数量。range(len(servers)):生成从0到列表长度减1的整数序列。
通过这些索引,我们就可以逐个访问列表中的元素。
不过,如果只是遍历元素,通常直接写 for server in servers 就足够了。
使用 enumerate() 同时获取索引和元素
如果既需要索引,又需要元素本身,可以使用 enumerate()。
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | 0 web01 |
enumerate() 会在遍历过程中,同时提供元素的索引和值。
如果希望编号从 1 开始,可以通过 start 参数指定起始编号:
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | 第 1 台服务器:web01 |
在输出巡检报告、生成带编号的任务清单时,这种写法非常实用。
在遍历过程中修改列表,需要注意什么?
列表是可变的,这意味着我们可以在程序运行过程中修改它。
不过,在使用 for 循环遍历列表时,如果一边遍历,一边直接添加或删除元素,可能会导致部分元素被跳过,或者程序行为与预期不一致。
例如:
1 | servers = ["web01", "web02", "db01", "cache01"] |
输出
1 | ['web01', 'db01', 'cache01'] |
这样的代码虽然可能运行,但直接在遍历同一个列表时删除元素,很容易造成逻辑问题。
如果确实需要筛选数据,通常可以创建一个新列表保存符合条件的元素:
1 | servers = ["web01", "web02", "db01", "cache01"] |
运行结果:
1 | ['web01', 'db01', 'cache01'] |
这里使用的是列表推导式。它可以根据条件创建一个新的列表,后续我们还可以专门学习这种简洁的写法。
对于初学者来说,先记住一个原则:如果需要在遍历过程中筛选元素,优先考虑创建新列表,而不是直接修改正在遍历的列表。
综合实战:整理服务器巡检清单
前面介绍了列表的创建、访问、切片、增删改、查找、排序、解包和循环遍历。
现在,我们把这些知识点组合起来,完成一个简单的服务器清单整理示例。
假设公司有一份初始巡检清单,其中包含重复的服务器名称。我们需要添加一台新服务器、移除一台已经下线的服务器,再按照名称排序,最后输出巡检任务列表。
1 | #!/usr/bin/env python3 |
运行结果:
1 | 初始清单: ['web03', 'web01', 'db01', 'web02', 'web01'] |
从结果可以看出,列表中的重复元素仍然存在。sort() 只负责排序,并不会自动去重。
如果业务要求每台服务器只巡检一次,就需要额外处理重复数据。例如,可以使用集合去重,但集合不保证保留原始顺序。如果既需要去重,又需要保留服务器第一次出现的顺序,可以使用:
1 | servers = ["web03", "web01", "db01", "web02", "web01"] |
运行结果:
1 | ['web03', 'web01', 'db01', 'web02'] |
从 Python 3.7 开始,字典保证按照插入顺序迭代,因此这里可以借助字典的键唯一性,在去重的同时保留元素第一次出现的顺序。
当然,实际的服务器巡检系统还需要考虑 SSH 连接、身份认证、超时处理、异常捕获和巡检结果记录等问题。这里我们先把重点放在列表操作上,为后续编写更完整的自动化脚本打好基础。
常见列表操作速查
学完上面的内容,我们把常用方法整理在一起,方便后续查阅。
| 操作 | 作用 | 示例 |
|---|---|---|
append(x) | 在末尾添加一个对象 | servers.append("web01") |
extend(iterable) | 将可迭代对象中的元素逐个添加 | servers.extend(new_servers) |
insert(i, x) | 在指定位置插入元素 | servers.insert(1, "web02") |
pop() | 删除并返回最后一个元素 | servers.pop() |
pop(i) | 删除并返回指定位置的元素 | servers.pop(0) |
remove(x) | 删除第一个匹配的元素 | servers.remove("web01") |
clear() | 清空列表 | servers.clear() |
index(x) | 查找第一个匹配元素的索引 | servers.index("web01") |
count(x) | 统计元素出现次数 | servers.count("web01") |
reverse() | 原地反转列表 | servers.reverse() |
sort() | 原地排序列表 | servers.sort() |
sorted(list) | 返回新的排序列表 | sorted(servers) |
len(list) | 获取元素数量 | len(servers) |
另外,还需要记住几个常见的操作规则:
- 使用索引访问元素时,索引从
0开始。 - 切片包含开始位置,但不包含结束位置。
append()添加一个对象,extend()添加多个元素。remove()删除第一个匹配项,pop()删除并返回指定位置的元素。sort()和reverse()会直接修改原列表,不会返回修改后的列表。- 如果需要同时获取索引和值,可以优先考虑
enumerate()。
写在最后
回到最开始的服务器巡检场景。
当服务器数量从几台增加到几十台、上百台时,我们需要的不只是一个保存服务器名称的地方,还需要能够灵活地添加服务器、移除下线节点、调整处理顺序,并逐个执行巡检任务。
Python 的 list 正好提供了这些基础能力。
通过这篇文章,我们学习了列表的创建、索引、切片、动态增删改、成员测试、排序、解包和循环遍历,也通过服务器清单示例把这些操作串联起来。
需要注意的是,列表虽然灵活,但并不是所有数据都适合用列表保存。如果数据不允许重复,可以考虑 set;如果需要根据主机名查找 IP 地址,可以考虑 dict;如果需要保存一组有顺序且容器自身不可变的数据,则可以考虑 tuple。
下一篇文章,我们将继续学习 Python 的 tuple,了解元组的创建、访问、解包,以及它与列表的区别。
学会使用列表,是编写自动化脚本的重要一步。真正掌握它的关键,不只是记住方法名称,而是能够根据实际需求,把这些操作组合起来解决问题。
