列表具有几个非常重要的特点:
- 使用**索引(Index)**访问元素,并且索引从
0开始。 - 支持负数索引,可以从列表末尾访问元素。
- 列表是可变的(Mutable),创建之后可以修改其中的元素。
- 可以使用
in判断元素是否存在。 - 可以包含其他列表,形成嵌套列表(Nested List)。
- 可以通过**解包(Unpacking)**将元素分配给多个变量。
- 可以通过**切片(Slicing)**获取列表中的一部分元素。
可以把列表简单理解成:
一个按照顺序排列、可以存放多个数据,并且允许修改的“数据容器”。
什么是列表(List)?
- 列表(List):列表是一种可以保存多个元素的序列(Sequence)类型。
- 序列(Sequence):指元素按照一定顺序排列,并且可以通过位置进行访问的数据结构。
- 可变(Mutable):列表创建之后,可以修改其中的元素。
- 零基索引(Zero-based Indexing):列表的第一个元素索引为
0。
最简单的列表:
cities = ['Los Angeles', 'London', 'Tokyo']
print(cities) # ['Los Angeles', 'London', 'Tokyo']
这个列表中有三个元素:
索引: 0 1 2
↓ ↓ ↓
Los Angeles London Tokyo
列表可以保存什么数据?
列表非常灵活。
它不仅可以保存字符串,还可以保存数字、布尔值,甚至其他列表。
例如:
numbers = [10, 20, 30]
names = ['Alice', 'Bob', 'Charlie']
mixed = [10, 'Hello', True, 3.14]
甚至可以把列表放进另一个列表:
data = ['Alice', 25, ['Python', 'Rust', 'C++']]
因此,列表可以保存:
| 数据类型 | 示例 |
|---|---|
字符串 str |
'Python' |
整数 int |
25 |
浮点数 float |
3.14 |
布尔值 bool |
True |
列表 list |
[1, 2, 3] |
列表的基本语法
创建列表时,需要使用:
[]
也就是一对方括号(Square Brackets)。
例如:
cities = ['Los Angeles', 'London', 'Tokyo']
多个元素之间使用逗号:
numbers = [1, 2, 3, 4, 5]
也可以创建空列表:
numbers = []
此时列表中没有任何元素。
什么是索引(Index)?
- 索引(Index):索引就是元素在序列中的位置编号。
- Python 的列表使用从
0开始的索引。
例如:
cities = ['Los Angeles', 'London', 'Tokyo']
对应关系:
| 元素 | 索引 |
|---|---|
'Los Angeles' |
0 |
'London' |
1 |
'Tokyo' |
2 |
因此:
print(cities[0]) # Los Angeles
访问列表元素的基本语法:
列表名[索引]
例如:
cities[1]
得到:
London
为什么第一个元素是 0?
这是 Python 的**零基索引(Zero-based Indexing)**规则。
也就是说:
第 1 个元素 → 索引 0
第 2 个元素 → 索引 1
第 3 个元素 → 索引 2
例如:
numbers = [10, 20, 30]
print(numbers[0]) # 10
print(numbers[1]) # 20
print(numbers[2]) # 30
因此要特别注意:
第一个元素的位置是第 1 个,但它的索引是
0。
使用负数索引
除了正数索引之外,Python 还支持负数索引(Negative Indexing)。
负数索引从列表末尾开始:
正数索引:
0 1 2
↓ ↓ ↓
['Los Angeles', 'London', 'Tokyo']
负数索引:
-3 -2 -1
↓ ↓ ↓
['Los Angeles', 'London', 'Tokyo']
例如:
cities = ['Los Angeles', 'London', 'Tokyo']
print(cities[-1]) # Tokyo
print(cities[-2]) # London
print(cities[-3]) # Los Angeles
其中:
cities[-1]
特别常用,它表示:
获取列表中的最后一个元素。
使用 list() 创建列表
除了使用 [],还可以使用:
list()
list() 是 Python 的内置函数(Built-in Function),也可以理解为列表构造函数。
它可以把一个**可迭代对象(Iterable)**转换成列表。
例如:
developer = 'Jessica'
result = list(developer)
print(result) # ['J', 'e', 's', 's', 'i', 'c', 'a']
因为字符串可以一个字符一个字符地访问,所以可以转换成列表。
什么是可迭代对象(Iterable)?
- Iterable(可迭代对象):可以按照顺序,一次访问其中一个元素的对象。
例如字符串:
name = 'Jessica'
可以依次访问:
J
e
s
s
i
c
a
所以字符串是一个可迭代对象。
以后学习 for 循环时,会经常遇到这个概念。
使用 len() 获取列表长度
如果想知道列表中有多少个元素,可以使用:
len()
len 是 length(长度) 的缩写。
例如:
numbers = [1, 2, 3, 4, 5]
print(len(numbers)) # 5
这里:
len(numbers)
表示:
获取
numbers中元素的数量。
注意:
numbers = [10, 20, 30]
列表长度是:
3
但最后一个元素的索引是:
2
因为:
元素数量:3
索引:
0
1
2
所以:
长度(Length)和最大索引(Maximum Index)不是同一个概念。
修改列表中的元素
列表和字符串一个非常重要的区别是:
列表是可变的(Mutable)。
也就是说,列表创建之后,可以修改其中的元素。
例如:
programming_languages = ['Python', 'Java', 'C++', 'Rust']
programming_languages[0] = 'JavaScript'
print(programming_languages)
# ['JavaScript', 'Java', 'C++', 'Rust']
这里:
programming_languages[0]
原本是:
Python
执行:
programming_languages[0] = 'JavaScript'
之后变成:
JavaScript
列表索引不能超出范围
修改列表元素时,必须使用有效的索引。
例如:
programming_languages = ['Python', 'Java', 'C++', 'Rust']
它只有:
0
1
2
3
因此下面的代码是错误的:
programming_languages[10] = 'JavaScript'
会产生:
IndexError: list assignment index out of range
IndexError 可以理解为:
索引错误:你访问或修改了不存在的位置。
删除列表中的元素
可以使用 Python 的:
del
关键字删除指定位置的元素。
例如:
developer = ['Jane Doe', 23, 'Python Developer']
del developer[1]
print(developer) # ['Jane Doe', 'Python Developer']
删除之前:
索引: 0 1 2
↓ ↓ ↓
Jane Doe 23 Python Developer
执行:
del developer[1]
之后:
['Jane Doe', 'Python Developer']
注意,删除元素后,后面的元素会向前移动。
使用 in 判断元素是否存在
如果想检查某个元素是否存在于列表中,可以使用:
in
例如:
programming_languages = ['Python', 'Java', 'C++', 'Rust']
print('Rust' in programming_languages) # True
print('JavaScript' in programming_languages) # False
in 会返回一个布尔值:
True
或者:
False
可以把它理解成:
“这个元素在不在列表里?”
in 的实际应用
例如:
users = ['Alice', 'Bob', 'Charlie']
if 'Alice' in users:
print('User exists') # User exists
这种写法在实际开发中非常常见,例如:
- 判断用户是否存在。
- 判断商品是否存在。
- 判断某个选项是否合法。
- 判断某个数据是否已经保存。
什么是嵌套列表(Nested List)?
列表中可以保存另一个列表。
这种结构叫:
嵌套列表(Nested List)
例如:
developer = ['Alice', 25, ['Python', 'Rust', 'C++']]
这里最外层列表包含三个元素:
developer
│
├── 0 → 'Alice'
│
├── 1 → 25
│
└── 2 → ['Python', 'Rust', 'C++']
其中索引 2 对应的元素本身又是一个列表。
访问嵌套列表
首先:
developer = ['Alice', 25, ['Python', 'Rust', 'C++']]
print(developer[2])
# ['Python', 'Rust', 'C++']
这里:
developer[2]
获取的是整个内部列表。
如果想继续获取内部列表中的 Rust:
print(developer[2][1]) # Rust
可以理解为:
developer[2]
↓
['Python', 'Rust', 'C++']
↓
[1]
↓
Rust
因此:
developer[2][1]
就是:
先找到外层列表索引
2的元素,再找到这个内部列表索引1的元素。
什么是列表解包(Unpacking)?
- 解包(Unpacking):把一个列表中的多个元素,一次性分配给多个变量。
例如:
developer = ['Alice', 34, 'Rust Developer']
name, age, job = developer
print(name) # Alice
print(age) # 34
print(job) # Rust Developer
相当于:
'Alice' → name
34 → age
'Rust Developer' → job
因此:
name
保存:
Alice
age 保存:
34
job 保存:
Rust Developer
解包时数量需要匹配
例如:
developer = ['Alice', 34, 'Rust Developer']
name, age, job = developer
右边有:
3 个元素
左边也有:
3 个变量
所以可以正常解包。
但是:
name, age, job, city = developer
左边需要 4 个值,而右边只有 3 个。
因此会出现:
ValueError
完整错误类似:
ValueError: not enough values to unpack (expected 4, got 3)
意思是:
解包失败:期望得到 4 个值,但实际上只有 3 个。
使用 * 收集剩余元素
如果想让某个变量接收剩余的所有元素,可以使用:
*
例如:
developer = ['Alice', 34, 'Rust Developer']
name, *rest = developer
print(name) # Alice
print(rest) # [34, 'Rust Developer']
这里:
name
获取第一个元素:
Alice
而:
*rest
会收集剩余元素。
因此:
rest
最终得到:
[34, 'Rust Developer']
注意:
使用
*收集剩余元素时,得到的仍然是一个列表。
什么是列表切片(Slicing)?
除了获取单个元素,还可以一次获取列表中的一部分。
这种操作叫:
切片(Slicing)
基本语法:
list[start:stop:step]
三个部分分别表示:
| 参数 | 含义 |
|---|---|
start |
开始位置 |
stop |
结束位置,但不包含该位置 |
step |
每次移动多少个位置 |
其中 step 是可选的。
基本切片示例
例如:
desserts = ['Cake', 'Cookies', 'Ice Cream', 'Pie', 'Brownies']
print(desserts[1:4])
# ['Cookies', 'Ice Cream', 'Pie']
对应索引:
索引: 0 1 2 3 4
↓ ↓ ↓ ↓ ↓
元素: Cake Cookies Ice Cream Pie Brownies
└────────────┬────────────┘
[1:4]
切片:
desserts[1:4]
会获取:
索引 1
索引 2
索引 3
但是不包含索引 4。
因此:
切片遵循“左闭右开”原则:包含
start,不包含stop。
省略 start 和 stop
切片中的某些参数可以省略。
例如:
numbers = [1, 2, 3, 4, 5]
从开头获取到索引 2:
print(numbers[:3]) # [1, 2, 3]
从索引 2 获取到最后:
print(numbers[2:]) # [3, 4, 5]
获取整个列表:
print(numbers[:]) # [1, 2, 3, 4, 5]
使用 step 指定步长
切片还可以使用第三个参数:
list[start:stop:step]
例如:
numbers = [1, 2, 3, 4, 5, 6]
print(numbers[1::2]) # [2, 4, 6]
这里:
start = 1
stop = 省略
step = 2
从索引 1 开始:
索引: 0 1 2 3 4 5
↓ ↓ ↓ ↓ ↓ ↓
元素: 1 2 3 4 5 6
↑ ↑ ↑
2 4 6
每次向后移动 2 个位置,因此得到:
[2, 4, 6]
列表切片速查表
假设:
numbers = [1, 2, 3, 4, 5, 6]
| 写法 | 含义 | 结果 |
|---|---|---|
numbers[:] |
获取全部元素 | [1, 2, 3, 4, 5, 6] |
numbers[:3] |
从开头到索引 3 之前 | [1, 2, 3] |
numbers[2:] |
从索引 2 到结尾 | [3, 4, 5, 6] |
numbers[1:4] |
获取索引 1~3 | [2, 3, 4] |
numbers[::2] |
从头开始,每隔 2 个取一个 | [1, 3, 5] |
numbers[1::2] |
从索引 1 开始,每隔 2 个取一个 | [2, 4, 6] |
列表的重要特点
| 特点 | 说明 |
|---|---|
| 有序(Ordered) | 元素按照一定顺序保存 |
| 可变(Mutable) | 创建之后可以修改元素 |
| 允许重复 | 相同的数据可以出现多次 |
| 支持索引 | 可以通过索引访问元素 |
| 支持负索引 | 可以从列表末尾访问元素 |
| 支持切片 | 可以获取列表的一部分 |
| 支持嵌套 | 列表中可以存放列表 |
| 支持解包 | 可以把元素分配给多个变量 |
常见操作速查
| 操作 | 示例 | 作用 |
|---|---|---|
| 创建列表 | numbers = [1, 2, 3] |
创建一个列表 |
| 访问元素 | numbers[0] |
获取第一个元素 |
| 访问最后一个 | numbers[-1] |
获取最后一个元素 |
| 修改元素 | numbers[0] = 10 |
修改元素 |
| 删除元素 | del numbers[0] |
删除元素 |
| 判断存在 | 2 in numbers |
判断元素是否存在 |
| 获取长度 | len(numbers) |
获取元素数量 |
| 转换列表 | list("abc") |
将可迭代对象转换成列表 |
| 列表切片 | numbers[1:3] |
获取部分元素 |
| 列表解包 | a, b, c = numbers |
将元素分配给变量 |
初学者容易犯的错误
❌ 错误一:认为第一个元素的索引是 1
错误理解:
第一个元素 → 1
正确:
第一个元素 → 0
例如:
numbers = [10, 20, 30]
print(numbers[0]) # 10
❌ 错误二:忘记切片不包含 stop
numbers = [1, 2, 3, 4, 5]
print(numbers[1:4]) # [2, 3, 4]
不是:
[2, 3, 4, 5]
记住:
[start:stop]包含 start,不包含 stop。
❌ 错误三:访问不存在的索引
numbers = [1, 2, 3]
print(numbers[5])
会产生:
IndexError
因为有效索引只有:
0、1、2
❌ 错误四:解包时变量数量不匹配
numbers = [1, 2, 3]
a, b = numbers
会产生:
ValueError
因为:
变量数量:2
元素数量:3
如果需要接收剩余元素,可以使用:
a, *rest = numbers
print(a) # 1
print(rest) # [2, 3]
总结
- **列表(List)**是一种可以保存多个数据的有序序列。
- Python 列表使用零基索引,第一个元素的索引是
0。 - 可以使用负索引从列表末尾访问元素,
-1表示最后一个元素。 - 列表是**可变(Mutable)**的,因此可以修改和删除元素。
list()可以把可迭代对象转换成列表。len()可以获取列表中元素的数量。in可以判断某个元素是否存在于列表中。- 列表可以嵌套其他列表,通过多个索引可以逐层访问。
- **解包(Unpacking)**可以将列表中的元素分配给多个变量。
*可以在解包时收集剩余元素。- **切片(Slicing)**使用
start:stop:step获取列表的一部分。 - 切片中的
stop不会被包含,这是使用列表切片时最需要记住的规则之一。
一句话理解列表:列表就是一个“有顺序、可以修改、可以存放多个数据”的容器。索引负责找元素,切片负责取一部分,解包负责把元素分配给变量。