# Python 列表：把一整列数据装进一个变量，让 for 循环挨个处理

承接上一篇的 for 循环：用方括号把一串值装进一个名字，按从 0 开始的索引取其中一项、用 len() 数个数、用 append() 往末尾加，并让 for 直接逐个处理列表元素。

> 列表与索引 · 循环与重复执行 · 自动化入门 · 约 8 分钟 · 10 月 08 日

## 本篇要点

1. 列表用方括号把一串值按顺序装进一个变量，写法是 `名单 = ["张三", "李四", "王五"]`，它是和数字、字符串一样可以赋给变量的值。
2. 用 `列表[编号]` 取其中一项，编号从 0 开始，所以三项的有效索引是 0、1、2，写 `名单[3]` 会报 IndexError；负数索引从右往左数，`名单[-1]` 取最后一项。
3. `len(列表)` 返回元素个数，最后一个元素的索引是 `len(列表) - 1`。
4. 把列表放在 `in` 右边，`for` 会一个一个取出列表元素装进循环变量，循环的写法、缩进和机制都不变，只是“供货方”从 range 的数字换成了列表的数据；列表有多少项，循环就跑多少遍，不用再数、不用改代码。
5. `列表.append(新项)` 把一项加到末尾，它改的是原列表本身、返回值是 None，所以不能写 `变量 = 变量.append(...)`。
6. 先建一个空列表 `[]` 当筐，在循环里用 `if` 判断、合格的用 `append` 放进去，就能一边遍历一边攒出新列表；准备筐的那行要放在循环外。

---

上一篇结尾留了一个尾巴：`for` 循环能把同一段代码跑很多遍，可是“跑几遍”这件事，你得自己数好、写进 `range(1, 6)` 里。表格今天 200 行、明天 1500 行，没人愿意每天先数一遍再改代码。当时说，等学会了能装一串数据的容器，把 `range(1, 6)` 换成那份数据就行——这一篇就来补上这个容器：**列表**。

## 先看一个装不下的问题

回到最朴素的写法。假设你有五个要处理的数字：

```python
数据1 = 30
数据2 = 45
数据3 = 12
数据4 = 88
数据5 = 60
```

变量确实能“记住数据”，可一个变量名只对应一个值。五个就写五行，五百个就写五百行。更麻烦的是，写完之后你没法用一句“挨个处理一下”把它们跑一遍，因为它们之间没有任何关系，只是五个同名不同号的独立变量。

我们缺的不是“能记住东西的盒子”，而是“能按顺序记住一串东西的盒子”。

## 列表：一串值装进一个名字

要装一串值，把值用方括号括起来，中间用逗号隔开：

```python
名单 = ["张三", "李四", "王五"]
```

这一行装下的，是刚才要写五个变量才装得下的东西，而且只用一个名字。这个新东西叫**列表**（list）。它和数字、字符串一样，是可以赋给变量的一种值，只是它里面装的不是单个值，而是一串按顺序排好的值。[1]

几个第一眼就该知道的性质：

- 外面的方括号 `[]` 是列表的标志。缺了它，`"张三"` 就只是一个普通字符串。
- 逗号是分隔符，每两项之间一个；最后一项后面不加逗号也行。
- 顺序有意义。列表是“排好队”的，谁在前谁在后，它记得清清楚楚。
- 里面的值可以是数字、字符串、布尔值，甚至混着放；但绝大多数时候你会让它们类型一致——一列名字就都是名字，一列金额就都是数字。

## 用序号取出其中一个

装进去之后得能拿单个值出来用。列表给每个位置编了号，用**索引**去取：列表名后面紧跟方括号，方括号里填位置编号。

```python
名单 = ["张三", "李四", "王五"]
print(名单[0])   # 张三
print(名单[1])   # 李四
print(名单[2])   # 王五
```

这里有个和直觉不一样的地方：**编号从 0 开始，不是从 1 开始**。第一个元素的索引是 0，第二个是 1。[1] 这和上一篇 `range()` 从 0 开始是同一个习惯——你还记得 `range(5)` 给出的是 0、1、2、3、4 吧，列表也这么数。

| 位置 | 第 1 个 | 第 2 个 | 第 3 个 |
| --- | --- | --- | --- |
| 索引写法 | `名单[0]` | `名单[1]` | `名单[2]` |
| 取到什么 | 张三 | 李四 | 王五 |

三个元素，有效索引就是 0、1、2。写成 `名单[3]`，程序会直接报错 `IndexError: list index out of range`——它不是在说“没找到”，而是在说“这个位置根本不存在”。[2]

还有一个很好用的写法：**索引可以是负数，意思是从右往左数**。`名单[-1]` 取最后一个，`名单[-2]` 取倒数第二个。[1]

```python
print(名单[-1])   # 王五
```

`-1` 代表最后一个，这让“取列表末尾那一项”变得很方便，因为你不用去数它到底排在第几位。

## 用 len() 数一数有几个

想知道列表里有几项，用内置函数 `len()`：

```python
名单 = ["张三", "李四", "王五"]
print(len(名单))   # 3
```

`len()` 交回元素个数。[1] 把它和索引放在一起，就能推出一条很有用的关系：**最后一个元素的索引是 `len(列表) - 1`**。三个元素，最后一个是 `名单[2]`，正好是 `len(名单) - 1`。记住这条，你基本不会再顺手把最后一项写成 `名单[3]` 了。

## 让 for 循环直接挨个处理

现在是这一篇的正题。上一篇里 `for` 是这样用的：

```python
for 序号 in range(1, 4):
    print(序号)
```

我们讲那一篇时说过，`for` 真正在做的事是“从 `in` 右边那个东西里，一个一个取出来，装进循环变量”。`range(1, 4)` 交出的是一串数字。**那如果 `in` 右边换成一个列表呢？**——`for` 就一个一个地把列表里的元素取出来：

```python
名单 = ["张三", "李四", "王五"]
for 名字 in 名单:
    print(f"请 {名字} 确认签字。")
```

输出三行：请张三、请李四、请王五。

请对照上一篇记住的机制看这里发生了什么。循环的写法一个字没改：冒号、缩进、循环变量，全都照旧。变的只有一件——`in` 右边从“一串数字”换成了“一串数据”。每一轮开头，循环变量 `名字` 被赋成列表里的下一个元素，然后执行循环体，再取下一个，直到列表取完为止。[2]

| 轮次 | 循环变量 `名字` | 这一轮打印 |
| --- | --- | --- |
| 第 1 轮 | 张三 | 请 张三 确认签字。 |
| 第 2 轮 | 李四 | 请 李四 确认签字。 |
| 第 3 轮 | 王五 | 请 王五 确认签字。 |

这正好接上了上一篇结尾的承诺。那时你写 `range(1, 6)`，是因为手里只有数字；现在手里的列表直接递给 `for`，**它有多少项，循环就跑多少遍，你不用数、也不用改代码**。明天表格从 200 行长到 1500 行，列表自然变长，循环跟着变——“重复次数写死”这个限制，到这里才算真正拿掉。

还有一点要分清：循环变量 `名字` 每轮拿到的，已经不再是 1、2、3 这样的编号，而是列表里的实际内容。所以你直接用 `名字` 说话就行，不用再绕一圈写成 `名单[名字]`。

## 用 append 往末尾加东西

列表建好之后还能继续长。想加一项，用 `append()`：

```python
名单 = ["张三", "李四"]
名单.append("王五")
print(名单)   # ['张三', '李四', '王五']
```

`append` 把新的一项加到列表末尾。[2] 它的写法和前面见过的东西不一样，有两个点要看清。

第一，**点号**。`名单.append("王五")` 里那个点，是“让 `名单` 这个列表去做一件事”的意思；`append` 是列表自带的能力，术语叫**方法**。你先把它读成“给名单追加王五”就行。

第二，**它改的是名单本身，不会给你一个新列表**。所以正确写法是直接 `名单.append("王五")`，加完之后原来的 `名单` 就多了一项。这里有一个新手几乎必踩的坑：

```python
名单 = 名单.append("王五")   # 错！
```

这么写的后果是，`名单` 被赋成了 `append` 的返回值——而 `append` 的返回值是 `None`（空），不是列表。[2] 于是 `名单` 从“一个列表”变成了“空”，后面再加东西就会报错。记住：**`append` 只管往原来的列表里加，不负责把列表交回给你**，所以不要写 `变量 = 变量.append(...)`。

## 把两件事合起来：一边循环，一边往里攒

`append` 最常出现的场合，是配着 `for` 循环用：先准备一个空列表当“筐”，循环里逐条判断，合格的往里放。

```python
原始数量 = [1, 5, 8, 2, 9, 4]
合格数量 = []
for 件数 in 原始数量:
    if 件数 >= 5:
        合格数量.append(件数)
print(合格数量)   # [5, 8, 9]
```

`合格数量 = []` 是个空列表，一个元素都没有，正等着往里装；`[]` 就是“空列表”的标准写法。循环里那条 `if` 每轮判断一次：够 5 件，就把这一项放进筐里。跑完，筐里就是 `[5, 8, 9]`。

这一段其实和上一篇的累加账本是同一个套路。你还记得那个 `合计 = 0` 吗：**准备筐的那行在循环外（否则每轮清空），干活的那行在循环内**。只不过累加是拿数字往一个数上叠，这里是拿数据往一个列表里放——缩进的道理一模一样。

## 今天就到这里

现在你有了一个能按顺序装一串数据的容器：能按索引取其中一项，能用 `len()` 数个数，能用 `append()` 往里加，还能把整个列表直接交给 `for` 挨个处理。上一篇那句“重复次数写死”的抱怨，到这里有了第一批解法。

不过这一篇里的数据还是你一个个手打进方括号里的。真实的表格不在代码里，而是躺在某个 `.csv` 或 `.xlsx` 文件里。怎么把它读进来、变成这样一个能交给 `for` 的列表，是下一步要解决的事。

## 术语表

- 列表（list）：用方括号把一串值按顺序装进一个变量的值，可以整体交给 `for` 处理，也能单独取用其中一项。
- 索引：`列表[编号]` 里方括号中的位置编号，从 0 开始，负数表示从右往左数，越界会报 IndexError。
- len()：内置函数，返回列表里元素的数量，用来知道列表有多长、末项索引是几。
- append()：列表的方法，把一项加到末尾，修改的是列表本身，返回值是 None。
- 方法（点号调用）：写成 `对象.方法(...)`，表示让这个对象去做一件事，比如 `名单.append(...)`。

## 来源

1. [Python 官方教程（中文）·3. Python 速览——列表用方括号逗号分隔创建，支持索引（从 0 开始、可为负数）与切片，len() 返回元素个数](https://docs.python.org/zh-cn/3/tutorial/introduction.html)
2. [Python 官方教程（中文）·5. 数据结构——append() 在末尾添加一项，仅修改列表的方法返回 None，越界索引引发 IndexError，可直接用 for 遍历列表](https://docs.python.org/zh-cn/3/tutorial/datastructures.html)

---

原文：https://pangzhengboyin.com/articles/python-list-index-append-iteration-02a6a575

> **庞征博引** · 想学的，慢慢都会
>
> 庞征博引是把想学的东西写成连载的 AI 学习工具。说出想学什么，它会先了解你的基础，再把主题写成一篇篇 5–10 分钟能读完的文章；边读边问，接下来学什么跟着你走。这篇就是这样写出来的。
>
> 开始你自己的连载 → https://pangzhengboyin.com
