3.2. 列表简介

列表是 Python 的主力数据类型。如果您对列表的唯一经验是 Visual Basic 中的数组或(上帝保佑)Powerbuilder 中的数据存储,请准备好迎接 Python 列表。

Note
Python 中的列表类似于 Perl 中的数组。在 Perl 中,存储数组的变量始终以 @ 字符开头;在 Python 中,变量可以任意命名,Python 会在内部跟踪数据类型。
Note
Python 中的列表比 Java 中的数组强大得多(尽管如果您真的只想使用数组的功能,它也可以用作数组)。一个更好的类比是 ArrayList 类,它可以容纳任意对象,并且可以在添加新项目时动态扩展。

3.2.1. 定义列表

示例 3.6. 定义列表

>>> li = ["a", "b", "mpilgrim", "z", "example"] 1
>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[0]                                       2
'a'
>>> li[4]                                       3
'example'
1 首先,定义一个包含五个元素的列表。请注意,它们保留了原始顺序。这不是偶然的。列表是用方括号括起来的有序元素集。
2 列表可以像从零开始的数组一样使用。任何非空列表的第一个元素始终是 li[0]
3 这个五元素列表的最后一个元素是 li[4],因为列表始终是从零开始的。

示例 3.7. 负列表索引

>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[-1] 1
'example'
>>> li[-3] 2
'mpilgrim'
1 负索引从列表的末尾开始倒序访问元素。任何非空列表的最后一个元素始终是 li[-1]
2 如果您对负索引感到困惑,可以这样理解:li[-n] == li[len(li) - n]。因此,在此列表中,li[-3] == li[5 - 3] == li[2]

示例 3.8. 切片列表

>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[1:3]  1
['b', 'mpilgrim']
>>> li[1:-1] 2
['b', 'mpilgrim', 'z']
>>> li[0:3]  3
['a', 'b', 'mpilgrim']
1 您可以通过指定两个索引来获取列表的子集,称为“切片”。返回值是一个新列表,其中包含列表的所有元素,按顺序排列,从第一个切片索引(在本例中为 li[1])开始,到但不包括第二个切片索引(在本例中为 li[3])。
2 如果一个或两个切片索引为负数,则切片仍然有效。如果您觉得有帮助,可以这样理解:从左到右读取列表,第一个切片索引指定您想要的第一个元素,第二个切片索引指定您不想要的第一个元素。返回值是两者之间的所有内容。
3 列表是从零开始的,因此 li[0:3] 返回列表的前三个元素,从 li[0] 开始,到但不包括 li[3]

示例 3.9. 切片简写

>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li[:3] 1
['a', 'b', 'mpilgrim']
>>> li[3:] 2 3
['z', 'example']
>>> li[:]  4
['a', 'b', 'mpilgrim', 'z', 'example']
1 如果左切片索引为 0,则可以将其省略,并隐含为 0。因此,li[:3]示例 3.8“切片列表” 中的 li[0:3] 相同。
2 同样,如果右切片索引是列表的长度,则可以将其省略。因此,li[3:]li[3:5] 相同,因为此列表有五个元素。
3 请注意此处的对称性。在这个五元素列表中,li[:3] 返回前 3 个元素,li[3:] 返回最后两个元素。实际上,无论列表的长度如何,li[:n] 始终返回前 n 个元素,li[n:] 始终返回其余元素。
4 如果两个切片索引都省略,则包含列表的所有元素。但这与原始的 li 列表不同;它是一个恰好具有所有相同元素的新列表。li[:] 是创建列表完整副本的简写。

3.2.2. 向列表添加元素

示例 3.10. 向列表添加元素

>>> li
['a', 'b', 'mpilgrim', 'z', 'example']
>>> li.append("new")               1
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']
>>> li.insert(2, "new")            2
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new']
>>> li.extend(["two", "elements"]) 3
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
1 append 将单个元素添加到列表的末尾。
2 insert 将单个元素插入列表中。数字参数是被挤出位置的第一个元素的索引。请注意,列表元素不需要唯一;现在有两个独立的元素的值为 'new'li[2]li[6]
3 extend 连接列表。请注意,您不会使用多个参数调用 extend;您使用一个参数(一个列表)调用它。在这种情况下,该列表有两个元素。

示例 3.11. extendappend 之间的区别

>>> li = ['a', 'b', 'c']
>>> li.extend(['d', 'e', 'f']) 1
>>> li
['a', 'b', 'c', 'd', 'e', 'f']
>>> len(li)                    2
6
>>> li[-1]
'f'
>>> li = ['a', 'b', 'c']
>>> li.append(['d', 'e', 'f']) 3
>>> li
['a', 'b', 'c', ['d', 'e', 'f']]
>>> len(li)                    4
4
>>> li[-1]
['d', 'e', 'f']
1 列表有两个方法,extendappend,它们看起来做的是同一件事,但实际上完全不同。extend 接受一个参数,该参数始终是一个列表,并将该列表的每个元素添加到原始列表中。
2 在这里,您最初有一个包含三个元素('a''b''c')的列表,并且您使用另一个包含三个元素('d''e''f')的列表扩展了该列表,因此您现在有了一个包含六个元素的列表。
3 另一方面,append 接受一个参数,该参数可以是任何数据类型,并简单地将其添加到列表的末尾。在这里,您使用单个参数调用 append 方法,该参数是一个包含三个元素的列表。
4 现在,最初包含三个元素的原始列表包含四个元素。为什么是四个?因为您刚刚追加的最后一个元素本身就是一个列表。列表可以包含任何类型的数据,包括其他列表。这可能是您想要的,也可能不是。如果您指的是 extend,请不要使用 append

3.2.3. 搜索列表

示例 3.12. 搜索列表

>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> li.index("example") 1
5
>>> li.index("new")     2
2
>>> li.index("c")       3
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
ValueError: list.index(x): x not in list
>>> "c" in li           4
False
1 index 在列表中查找值的第一次出现并返回索引。
2 index 在列表中查找值的第一次出现。在这种情况下,'new' 在列表中出现两次,位于 li[2]li[6],但 index 将仅返回第一个索引 2
3 如果在列表中找不到该值,Python 会引发异常。这与大多数语言明显不同,后者将返回一些无效的索引。虽然这看起来很烦人,但这是一件好事,因为这意味着您的程序将在问题根源处崩溃,而不是在您稍后尝试使用无效索引时崩溃。
4 要测试值是否在列表中,请使用 in,如果找到该值,则返回 True,否则返回 False
Note
在 2.2.1 版之前,Python 没有单独的布尔数据类型。为了弥补这一点,Python 接受布尔上下文(如 if 语句)中的几乎所有内容,具体规则如下:
  • 0 为假;所有其他数字均为真。
  • 空字符串("")为假,所有其他字符串均为真。
  • 空列表([])为假;所有其他列表均为真。
  • 空元组(())为假;所有其他元组均为真。
  • 空字典({})为假;所有其他字典均为真。
这些规则在 Python 2.2.1 及更高版本中仍然适用,但现在您也可以使用实际的布尔值,其值为 TrueFalse。请注意大小写;这些值与 Python 中的所有其他内容一样,区分大小写。

3.2.4. 删除列表元素

示例 3.13. 从列表中删除元素

>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> li.remove("z")   1
>>> li
['a', 'b', 'new', 'mpilgrim', 'example', 'new', 'two', 'elements']
>>> li.remove("new") 2
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two', 'elements']
>>> li.remove("c")   3
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
ValueError: list.remove(x): x not in list
>>> li.pop()         4
'elements'
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two']
1 remove 从列表中删除值的第一次出现。
2 remove删除值的第一次出现。在这种情况下,'new' 在列表中出现两次,但 li.remove("new") 仅删除了第一次出现。
3 如果在列表中找不到该值,Python 会引发异常。这反映了 index 方法的行为。
4 pop 是一个有趣的家伙。它执行两项操作:删除列表的最后一个元素,并返回删除的值。请注意,这与 li[-1] 不同,后者返回值但不更改列表,也与 li.remove(value) 不同,后者更改列表但不返回值。

3.2.5. 使用列表运算符

示例 3.14. 列表运算符

>>> li = ['a', 'b', 'mpilgrim']
>>> li = li + ['example', 'new'] 1
>>> li
['a', 'b', 'mpilgrim', 'example', 'new']
>>> li += ['two']                2
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two']
>>> li = [1, 2] * 3              3
>>> li
[1, 2, 1, 2, 1, 2]
1 列表也可以使用 + 运算符进行连接。list = list + otherlistlist.extend(otherlist) 具有相同的结果。但是,+ 运算符返回一个新的(连接的)列表作为值,而 extend 仅更改现有列表。这意味着 extend 更快,尤其是对于大型列表。
2 Python 支持 += 运算符。li += ['two'] 等效于 li.extend(['two'])+= 运算符适用于列表、字符串和整数,并且可以重载以适用于用户定义的类。(有关类的更多信息,请参见第 5 章。)
3 * 运算符作用于列表时,相当于一个重复器。 li = [1, 2] * 3 等价于 li = [1, 2] + [1, 2] + [1, 2],即将三个列表连接成一个。

列表的更多信息