geekdoc-python-zh/docs/pythonland/30.md

570 lines
20 KiB
Markdown
Raw Permalink Normal View History

2024-03-03 22:54:39 +08:00
# Python 列表:如何创建、排序、追加、移除等等
> 原文:[https://python.land/python-data-types/python-list](https://python.land/python-data-types/python-list)
Python 列表是最常用的数据结构之一,还有[字典](https://python.land/python-data-types/dictionaries)。Python 列表不仅仅是一个列表,还可以作为一个堆栈,甚至是一个队列。在本文中,我将解释您可能想知道的关于 Python 列表的一切:
* 如何创建列表,
* 修改它们,
* 如何对列表排序,
* 用一个 [for 循环](https://python.land/introduction-to-python/python-for-loop)或者一个[列表理解](https://python.land/deep-dives/list-comprehension)来循环一个列表的元素,
* 如何分割列表,
* 追加到 Python 列表,
* …以及更多!
我已经包含了许多工作代码示例来演示。
目录
* [如何创建 Python 列表](#How_to_create_a_Python_list "How to create a Python list")
* [访问 Python 列表元素](#Accessing_Python_list_elements "Accessing Python list elements")
* [添加和删除元素](#Adding_and_removing_elements "Adding and removing elements")
* [如何在 Python 中获取列表长度](#How_to_get_List_length_in_Python "How to get List length in Python")
* [统计列表中元素的出现次数](#Counting_element_occurrence_in_a_list "Counting element occurrence in a list")
* [检查项目是否在列表中](#Check_if_an_item_is_in_a_list "Check if an item is in a list")
* [查找列表中某项的索引](#Find_the_index_of_an_item_in_a_list "Find the index of an item in a list")
* [遍历列表元素](#Loop_over_list_elements "Loop over list elements")
* [Python 列表到字符串](#Python_list_to_string "Python list to string")
* [排序 Python 列表](#Sorting_Python_lists "Sorting Python lists")
* [切片](#Slicing "Slicing")
* [反转 Python 列表](#Reversing_Python_lists "Reversing Python lists")
* [了解关于 Python 列表的更多信息](#Learn_more_about_Python_lists "Learn more about Python lists")
## 如何创建 Python 列表
让我们首先创建一个列表:
```py
my_list = [1, 2, 3]
empty_list = []
```
列表包含常规的 Python 对象,用逗号分隔,并用括号括起来。列表中的元素可以有任意的[数据类型](https://python.land/python-data-types),并且可以混合使用。你甚至可以创建一个列表列表。以下列表都是有效的:
```py
my_list = [1, "Erik", { 'age': 39 }]
# This is a list with three lists inside
game_board = [[], [], []]
```
### 使用 list()函数
Python 列表和所有 Python 数据类型一样都是对象。list 的类叫做list小写 l如果想把另一个 Python 对象转换成 list可以使用 list()函数,它其实就是 list 类本身的构造函数。这个[函数](https://python.land/introduction-to-python/functions)接受一个参数:一个可迭代的对象。
所以你可以把任何可迭代的东西转换成一个列表。例如,您可以将 range 函数具体化为实际值的列表,或者将 Python 集或[元组](https://python.land/python-data-types/python-tuple)转换为列表:
```py
>>> list(range(1, 4))
[1, 2, 3]
>>> list({1, 2, 2, 2, 3})
[1, 2, 3]
>>> list( (1, 2, 3) )
[1, 2, 3]
```
## 访问 Python 列表元素
要访问单个列表元素,您需要知道该元素的位置。由于计算机从 0 开始计数,第一个元素在位置 0第二个元素在位置 1依此类推。
这里有几个例子:
```py
>>> my_list = [1, 2, 3]
>>> my_list[1]
2
>> my_list[0]
1
>> my_list[4]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
```
如您所见您无法访问不存在的元素。在这种情况下Python 抛出一个 IndexError [异常](https://python.land/deep-dives/python-try-except),解释为“列表索引超出范围”。在我关于[异常和 try 和 except 语句](https://python.land/deep-dives/python-try-except#Exception_best_practices)的文章中,我在最佳实践部分更深入地讨论了这个主题。推荐你读一读。
### 获取列表的最后一个元素
如果想从列表的末尾获取元素,可以提供一个负值。在这种情况下,我们从-1 而不是 0 开始计数。例如,要获取列表的最后一个元素,您可以这样做:
```py
>>> my_list = [1, 2, 3]
>>> my_list[-1] # get the last element
3
>>> my_list[-2] # get the 2nd last element
2
```
### 访问嵌套列表元素
访问嵌套的列表元素没有太大的不同。当您访问列表元素时,将返回该列表。因此,要请求列表中的元素,您需要再次使用几个括号:
```py
>>> my_list = [[1, 2], [3, 4], [5, 6]]
>>> my_list[0]
[1, 2]
>> my_list[0][0]
1
>>> my_list[2][1]
6
```
## 添加和删除元素
让我们看看如何添加和删除数据。有几种方法可以从列表中删除数据。你用什么,取决于你所处的情况。我将在本节中描述和演示它们。
### 追加到 Python 列表
列表对象有许多有用的内置方法,其中之一是 append 方法。当在列表上调用 append 时,我们将一个对象追加到列表的末尾:
```py
>>> my_list = [1, 2]
>>> my_list.append('a')
>>> my_list
[1, 2, 'a']
>>> my_list.append(4)
>>> my_list
[1, 2, 'a', 4]
```
### 组合或合并两个列表
添加元素的另一种方式是将一个列表中的所有元素添加到另一个列表中。有两种方法可以合并列表:
1. 用+运算符将它们相加。
2. 使用 extend 方法将一个列表中的所有元素添加到另一个列表中。
以下是如何将两个列表相加的方法。结果是一个新的第三个列表:
```py
>>> l1 = [1, 2]
>>> l2 = [3, 4]
>>> l3 = l1 + l2
>>> l3
[1, 2, 3, 4]
```
原始列表保持不变。另一种方法是使用 extend 方法用一个列表扩展另一个列表:
```py
>>> l1 = [1, 2]
>>> l2 = [3, 4]
>>> l1.extend(l2)
>>> l1
[1, 2, 3, 4]
>>> l2
[3, 4]
```
当 l1 用 l2 的元素扩展时l2 保持不变。将附加的所有值从 l2 扩展到 l1。
### 从列表中弹出项目
默认情况下pop()方法**移除并返回最后一项**,除非您给它一个索引参数。
下面是几个示例,演示了默认行为和给定索引时的行为:
```py
>>> my_list = [1, 2, 3, 4, 5]
>>> my_list.pop()
5
>>> my_list.pop()
4
>>> my_list.pop(0)
1
>>> my_list
[2, 3]
```
如果您熟悉[栈](https://en.wikipedia.org/wiki/Stack_(abstract_data_type))的概念,那么您现在可以在一个列表上只使用 append 和 pop 方法来构建一个栈!
### 使用 del()删除项目
从列表中删除或移除项目有多种方式。当 pop 返回从列表中删除的项目时,`del`删除它而不返回任何内容。事实上,您可以使用 del 删除任何对象,包括整个列表:
```py
>>> my_list = [1, 2, 3, 4, 5]
>>> del(my_list[0])
>>> my_list
[2, 3, 4, 5]
>>> del(my_list[2])
>>> my_list
[2, 3, 5]
>>> del(my_list)
>>> my_list
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'my_list' is not defined
```
### 从 Python 列表中移除特定值
如果要删除特定的值,可以使用 remove 方法。例如,如果您想删除列表中第一次出现的数字 2您可以按如下方式操作:
```py
>>> my_list = [1, 2, 3, 2, 5]
>>> my_list.remove(2)
>>> my_list
[1, 3, 2, 5]
>>> my_list.remove(2)
>>> my_list
[1, 3, 5]
>>> my_list.remove(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
```
如您所见,重复调用 remove 将删除额外的 2直到一个都不剩在这种情况下 Python 抛出一个 [ValueError 异常](https://python.land/deep-dives/python-try-except)。
### 移除或清除 Python 列表中的所有项目
要从列表中删除所有项目,使用`clear()`方法:
```py
>>> my_list = [1, 2, 3]
>>> my_list.clear()
>>> my_list
[]
```
### 从列表中删除重复项
没有特殊的函数或方法来删除列表中的重复项,但是我们可以使用多种技巧来这样做。最简单的,在我看来,就是使用一个 [Python 集合](https://python.land/python-data-types/python-set-the-why-and-how-with-example-code)。集合是对象的集合,就像列表一样,但是每个元素只能包含一个。更正式的说法是:集合是*不同*对象的*无序*集合。
通过将列表转换为集合,然后再转换回列表,我们已经有效地删除了所有重复项:
```py
>>> my_list = [1, 2, 2, 3, 5]
>>> my_set = set(my_list)
>>> my_set
{1, 2, 3, 5}
>>> list(my_set)
[1, 2, 3, 5]
```
在您自己的代码中,您可能希望使用这个更紧凑的版本:
```py
>>> my_list = [1, 2, 2, 3, 5]
>>> list(set(my_list))
[1, 2, 3, 5]
```
由于集合与列表非常相似,您甚至不必将它们转换回列表。如果 set 提供了您需要的东西,那么就用它来避免双重转换,使您的程序更快更有效。
Thank you for reading my tutorials. I write these in my free time, and it requires a lot of time and effort. I use ads to keep writing these *free* articles, I hope you understand! **Support me by disabling your adblocker on my website** or, alternatively, **[buy me some coffee](https://www.buymeacoffee.com/pythonland)**. It's much appreciated and allows me to keep working on this site!
### 替换列表中的项目
为了替换列表项,我们给给定的列表索引分配一个新值,如下所示:
```py
>>> my_list = [1, 2, 3, 4, 5]
>>> my_list[0] = 400
>>> my_list
[400, 2, 3, 4, 5]
```
## 如何在 Python 中获取列表长度
在 Python 中,我们使用`len`函数来获取对象的长度。列表也是如此:
```py
>>> my_list = [1, 2, 3, 4, 5]
>>> len(my_list)
5
```
如果你熟悉其他编程语言,比如 Java你可能会想为什么 Python 有这个功能。毕竟,它也可能是 list 的内置方法之一,就像`my_list.len()`一样。这是因为,在其他语言中,这通常会导致各种方法来获取对象的长度。例如,有些人会将这个函数称为`len`,有些人会将其称为 length还有一些人甚至不会实现这个函数而只是提供一个公共成员变量。而这也正是 Python 选择对这样一个常见操作的命名进行标准化的原因!
## 统计列表中元素的出现次数
不要把 count 函数和获取列表长度混为一谈,这是完全不同的。内置 counter 函数计算列表中特定值的出现次数。这里有一个例子:
```py
>>> my_list = [1, 2, 1, 4, 1, 7]
>>> my_list.count(1)
3
>>> my_list.count(4)
1
```
由于数字 1 在列表中出现了三次,`my_list.count(1)`返回 3。
## 检查项目是否在列表中
要检查项目是否在列表中,请使用以下语法:
```py
>>> my_list = [1, 2]
>>> if 1 in my_list:
... print("It's in the list")
...
It's in the list
```
## 查找列表中某项的索引
我们可以用索引方法找到一个条目在列表中的位置。例如在下面的列表中4 位于位置 3(请记住,我们从零开始计数):
```py
>>> my_list = [1, 2, 3, 4, 5]
>>> my_list.index(4)
3
```
index 方法有两个可选参数start 和 stop。有了这些我们可以继续寻找更多相同的价值观。如果我们提供一个开始值我们不需要提供一个结束值。现在让我们在下面的列表中找到这两个 4:
```py
my_list = [1, 2, 3, 4, 5, 4]
print(my_list.index(4))
# Output: 3
# We know there's a 4 at position 3 so
# let's continue our search from position 4
print(my_list.index(4, 4))
# Output: 5
```
如果你想对列表进行更高级的过滤,你应该去看看我的关于[列表理解](https://python.land/deep-dives/list-comprehension)的文章。
## 遍历列表元素
列表是[可迭代的](https://python.land/deep-dives/python-iterator),所以我们可以在列表的元素上使用 [for 循环](https://python.land/introduction-to-python/python-for-loop),就像我们可以在< iterable >语法中使用for<元素>来迭代任何其他元素一样:
```py
>>> my_list = [1, 2, 3, 4, 5]
>>> for n in my_list:
... print(n)
...
1
2
3
4
5
```
## Python 列表到字符串
在 Python 中,可以使用 str 函数将大多数对象转换为字符串:
```py
>>> str([1, 'abc', 2.3])
"[1, 'abc', 2.3]"
```
如果你感兴趣str 实际上是 [Python 字符串](https://python.land/introduction-to-python/strings)的基类,调用`str()`通过调用 str 类的构造函数构造一个新的 str 对象。这个构造函数检查提供的对象,并寻找一个名为`__str__`的特殊方法(也称为 dunder 方法)。如果存在,则调用此方法。没什么更多的了。
如果您创建了自己的[类和对象](https://python.land/objects-and-classes),您可以自己实现`__str__`函数来提供对象的可打印版本。
## 排序 Python 列表
要对 Python 列表进行排序,我们有两个选项:
1. 使用列表本身的内置排序方法。
2. 使用 Python 内置的 *sorted()* 函数。
选项一,内置方法,提供了一个就地排序,这意味着列表本身被修改。换句话说,这个函数不返回任何东西。相反,它会修改列表本身。
选项二返回一个新列表,原始列表保持不变。你使用哪一个取决于你所处的情况。
### 按升序就地列表排序
让我们从最简单的用例开始:按升序排序:
```py
>>> my_list = [10, 2, 5, 4, 2]
>>> my_list.sort()
>>> my_list
[2, 2, 4, 5, 10]
```
### 按降序就地列表排序
我们可以用一个反向参数调用 sort 方法。如果设置为 True排序将颠倒顺序:
```py
>>> my_list = [10, 2, 5, 4, 2]
>>> my_list.sort(reverse=True)
>>> my_list
[10, 5, 4, 2, 2]
```
### 使用排序的()
下面的例子演示了如何对列表进行升序排序,**返回一个新的列表**的结果:
```py
>>> my_list = [10, 2, 5, 4, 2]
>>> sorted(my_list)
[2, 2, 4, 5, 10]
>>> my_list
[10, 2, 5, 4, 2]
```
从最后一条语句可以看出,原来的列表没有变化。让我们再来一次,但现在按降序排列:
```py
>>> my_list = [10, 2, 5, 4, 2]
>>> sorted(my_list, reverse=True)
[10, 5, 4, 2, 2]
>>> my_list
[10, 2, 5, 4, 2]
```
### 不可排序列表
我们不能对所有列表进行排序,因为 Python 不能对所有类型进行相互比较。例如,我们可以对一系列数字进行排序,比如整数和浮点数,因为它们有一个确定的顺序。我们也可以对字符串列表进行排序,因为 Python 也能够比较字符串。
然而列表可以包含任何类型的对象我们不能比较完全不同的对象如数字和字符串。在这种情况下Python 抛出一个`TypeError`:
```py
>>> my_mixed_list = [1, 'a', 2, 'B']
>>> my_mixed_list.sort()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'str' and 'int'
```
尽管这个错误看起来有点神秘但只有当你知道发生了什么时它才是合乎逻辑的。为了对列表进行排序Python 需要对对象进行相互比较。所以在它的排序算法中在某个时候它检查a是否< 1因此产生了错误:`'<' not supported between instances of 'str' and 'int'`
## 切片
有时候你需要得到列表的一部分。Python 有一个强大的语法来做到这一点,称为切片,与其他一些编程语言相比,它使处理列表容易得多。切片适用于 Python 列表,但也适用于任何其他序列类型,如[字符串](https://python.land/introduction-to-python/strings)、[元组](https://python.land/python-data-types/python-tuple)和[范围](https://python.land/deep-dives/python-range)。
切片语法如下:
`my_list[start:stop:step]`
几个注意事项:
* `start`是要包含的第一个元素位置
* `stop`是排他的,意味着位置`stop`处的元素不会被包括在内。
* `step`是步长。稍后将详细介绍。
* `start`、`stop`、`step`都是可选的。
* 负值也可以使用。
为了解释切片是如何工作的,最好只看例子,并亲自尝试,这就是我们要做的:
```py
>>> my_list = [1, 2, 3, 4, 5, 6, 7, 8]
>>> my_list[0:3] # get the first three elements of a list
[1, 2, 3]
>>> my_list[:3] # start is 0 by default
[1, 2, 3]
>>> my_list[4:] # skip the first 4 elements
[5, 6, 7, 8]
```
### 步长值
默认情况下,步长值为 1。如果你增加它你可以跳过元素。让我们试试这个:
```py
>>> my_list = [1, 2, 3, 4, 5, 6, 7, 8]
>>> my_list[::2] # skip one each time
[1, 3, 5, 7]
```
### 倒退
像列表索引一样,我们也可以通过切片提供负数。这里有一个小小的 ASCII 艺术展示给你如何在列表中倒计数:
```py
my_list = [1 , 2, 3, 4, 5, 6]
-6 -5 -4 -3 -2 -1 (these are the index numbers)
```
请记住,为了后退,您需要设置一个负的步长:
```py
>>> my_list = [1, 2, 3, 4, 5, 6]
>>> my_list[-1:-3:-1]
[6, 5]
```
## 反转 Python 列表
在 Python 中,实际上有三种方法可以用来反转列表:
1. 就地反转,使用每个列表固有的内置反转方法
2. 使用负步长的列表分片会产生一个新列表
3. 用`reversed()`函数创建一个反向[迭代器](https://python.land/deep-dives/python-iterator)
在下面的代码片段中,我演示了这三个部分。以下各节将对它们进行详细说明:
[https://crumb . sh/embed/qd 2vr 57 bcpv](https://crumb.sh/embed/qd2VR57bcpV)
恢复 Python 列表的三种方法
### 使用内置的反向方法
`list.reverse()`方法执行就地反转,这意味着它对列表进行重新排序。换句话说,该方法不会以相反的顺序返回新的列表对象。下面是如何使用`reverse()`:
```py
>>> lst = [1, 2, 3, 4]
>>> lst.reverse()
>>> lst
[4, 3, 2, 1]
>>> lst.reverse()
>>> lst
[1, 2, 3, 4]
```
### 使用列表切片反转列表
虽然可以用每个列表都有的`list.reverse()`方法来反转列表,但是也可以用列表切片来反转列表,使用-1 的负步长。这里的不同之处在于列表分片会产生一个新的第二个列表。它保持原始列表不变:
```py
>>> lst = [1, 2, 3, 4]
>>> lst[::-1]
[4, 3, 2, 1]
>>> lst
[1, 2, 3, 4]
```
### 创建反向迭代器
最后,您可以使用`reversed()`内置函数,它创建一个[迭代器](https://python.land/deep-dives/python-iterator),反向返回给定 iterable(我们的列表)的所有元素。这种方法在 CPU 和内存使用方面非常便宜。它需要做的就是在 iterable 对象上向后走。它不需要移动数据,也不需要为第二个列表保留额外的内存。所以如果你需要逆向迭代一个(大)列表,这应该是你的选择。
以下是使用该功能的方法。请记住,您只能使用迭代器一次,但是创建一个新的迭代器很便宜:
```py
>>> lst = [1, 2, 3, 4]
>>> rev = reversed(lst)
>>> rev
<list_reverseiterator object at 0x0000023DB96A25C0>
>>> for i in rev:
... print(i)
...
4
3
2
1
```
## 了解关于 Python 列表的更多信息
因为有很多关于列表理解的内容要讲,所以我为这个主题专门写了一篇文章。一个 [Python list comprehension](https://python.land/deep-dives/list-comprehension) 是一个语言构造,我们用它来创建一个基于现有列表的列表,而不用创建 [for-loops](https://python.land/introduction-to-python/python-for-loop) 。
您可能喜欢的一些其他资源:
* [官方 Python 文档](https://docs.python.org/3/tutorial/datastructures.html)关于列表。
* 如果你对内部感兴趣:列表通常在内部实现为一个[链表](https://en.wikipedia.org/wiki/Linked_list)。
* Python 也有数组,它们非常相似,来自其他编程语言的人对这个术语应该很熟悉。它们存储数据的效率更高,但只能存储一种类型的数据。