Python列表值的灵活运用
2023-01-204.7k 阅读
Python 列表值的灵活运用
列表基础回顾
在深入探讨列表值的灵活运用之前,先来简单回顾一下 Python 列表的基础知识。列表是 Python 中最常用的数据结构之一,它是一个有序的可变序列,可以容纳不同类型的元素。通过方括号 []
来创建列表,元素之间用逗号 ,
分隔。例如:
my_list = [1, 'hello', 3.14, True]
这里 my_list
包含了整数、字符串、浮点数和布尔值四种不同类型的元素。列表的索引从 0 开始,我们可以通过索引来访问列表中的元素。例如,要访问 my_list
中的字符串 'hello'
,可以使用 my_list[1]
。
列表值的访问与修改
- 单个元素访问与修改
- 访问单个元素时,如上述通过索引获取列表中的元素。而修改单个元素也非常简单,直接通过索引赋值即可。例如:
my_list = [1, 2, 3]
print(my_list[1]) # 输出 2
my_list[1] = 20
print(my_list) # 输出 [1, 20, 3]
- 切片访问与修改
- 切片是 Python 中访问列表部分元素的强大方式。切片语法为
list[start:stop:step]
,start
是起始索引(包含),stop
是结束索引(不包含),step
是步长,默认值分别为 0、列表长度和 1。例如:
- 切片是 Python 中访问列表部分元素的强大方式。切片语法为
my_list = [1, 2, 3, 4, 5]
sub_list = my_list[1:3]
print(sub_list) # 输出 [2, 3]
- 切片也可以用于修改列表的部分值。例如,将
my_list
中索引 1 到 3(不包含 3)的元素替换为新的列表:
my_list = [1, 2, 3, 4, 5]
my_list[1:3] = [20, 30]
print(my_list) # 输出 [1, 20, 30, 4, 5]
- 如果步长不为 1,切片会按照指定步长获取元素。例如,获取
my_list
中从索引 0 开始,每隔一个元素的子列表:
my_list = [1, 2, 3, 4, 5]
sub_list = my_list[0::2]
print(sub_list) # 输出 [1, 3, 5]
- 当步长为负数时,可以实现反向切片。例如,将
my_list
反向:
my_list = [1, 2, 3, 4, 5]
reversed_list = my_list[::-1]
print(reversed_list) # 输出 [5, 4, 3, 2, 1]
列表值的添加与删除
- 添加元素
append()
方法:用于在列表末尾添加一个元素。例如:
my_list = [1, 2, 3]
my_list.append(4)
print(my_list) # 输出 [1, 2, 3, 4]
extend()
方法:用于将一个可迭代对象(如列表、元组等)的元素添加到列表末尾。例如:
my_list = [1, 2, 3]
new_elements = [4, 5]
my_list.extend(new_elements)
print(my_list) # 输出 [1, 2, 3, 4, 5]
insert()
方法:可以在指定索引位置插入一个元素。例如,在索引 1 处插入元素 10:
my_list = [1, 2, 3]
my_list.insert(1, 10)
print(my_list) # 输出 [1, 10, 2, 3]
- 删除元素
del
语句:可以根据索引删除列表中的元素。例如,删除my_list
中索引为 2 的元素:
my_list = [1, 2, 3]
del my_list[2]
print(my_list) # 输出 [1, 2]
pop()
方法:默认删除并返回列表的最后一个元素,也可以指定索引删除并返回指定位置的元素。例如:
my_list = [1, 2, 3]
popped = my_list.pop()
print(popped) # 输出 3
print(my_list) # 输出 [1, 2]
popped = my_list.pop(1)
print(popped) # 输出 2
print(my_list) # 输出 [1]
remove()
方法:根据元素值删除列表中的元素。如果列表中有多个相同值的元素,remove()
只会删除第一个。例如:
my_list = [1, 2, 2, 3]
my_list.remove(2)
print(my_list) # 输出 [1, 2, 3]
列表值的查找与计数
- 查找元素
index()
方法:用于查找列表中某个元素第一次出现的索引位置。如果元素不存在,会抛出ValueError
异常。例如:
my_list = [1, 2, 3, 2]
index = my_list.index(2)
print(index) # 输出 1
- 为了避免
ValueError
异常,可以先使用in
关键字判断元素是否在列表中。例如:
my_list = [1, 2, 3]
if 2 in my_list:
index = my_list.index(2)
print(index) # 输出 1
- 计数元素
count()
方法:用于统计列表中某个元素出现的次数。例如:
my_list = [1, 2, 2, 3]
count = my_list.count(2)
print(count) # 输出 2
列表值的排序与反转
- 排序
sort()
方法:对列表进行原地排序,即直接修改原列表,使其元素按升序排列。对于数字列表,直接进行数值大小排序;对于字符串列表,按字母顺序排序。例如:
num_list = [3, 1, 2]
num_list.sort()
print(num_list) # 输出 [1, 2, 3]
str_list = ['c', 'a', 'b']
str_list.sort()
print(str_list) # 输出 ['a', 'b', 'c']
- 如果要按降序排序,可以传递
reverse=True
参数。例如:
num_list = [3, 1, 2]
num_list.sort(reverse = True)
print(num_list) # 输出 [3, 2, 1]
- 对于包含不同类型元素的列表,直接排序会引发
TypeError
,因为 Python 无法确定不同类型元素的比较规则。例如:
mixed_list = [1, 'a']
try:
mixed_list.sort()
except TypeError as e:
print(f"Error: {e}")
sorted()
函数:与sort()
方法不同,sorted()
函数会返回一个新的已排序列表,原列表保持不变。例如:
num_list = [3, 1, 2]
new_sorted_list = sorted(num_list)
print(new_sorted_list) # 输出 [1, 2, 3]
print(num_list) # 输出 [3, 1, 2]
- 反转
reverse()
方法:对列表进行原地反转,即直接修改原列表,将元素顺序颠倒。例如:
my_list = [1, 2, 3]
my_list.reverse()
print(my_list) # 输出 [3, 2, 1]
- 也可以使用切片
[::-1]
来实现列表反转,这种方式会返回一个新的反转后的列表,原列表不变。例如:
my_list = [1, 2, 3]
new_reversed_list = my_list[::-1]
print(new_reversed_list) # 输出 [3, 2, 1]
print(my_list) # 输出 [1, 2, 3]
列表值的嵌套
- 创建嵌套列表
- 列表可以包含其他列表,形成嵌套结构。例如,创建一个二维列表:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
这里 matrix
是一个包含三个子列表的列表,每个子列表又包含三个元素,可以看作是一个 3x3 的矩阵。
2. 访问嵌套列表的值
- 访问嵌套列表中的元素需要使用多层索引。例如,要访问
matrix
中第二行第三列的元素(索引从 0 开始),可以使用matrix[1][2]
:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(matrix[1][2]) # 输出 6
- 修改嵌套列表的值
- 同样通过多层索引来修改嵌套列表中的元素。例如,将
matrix
中第一行第二列的元素修改为 10:
- 同样通过多层索引来修改嵌套列表中的元素。例如,将
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix[0][1] = 10
print(matrix) # 输出 [[1, 10, 3], [4, 5, 6], [7, 8, 9]]
- 遍历嵌套列表
- 可以使用多层循环来遍历嵌套列表。例如,遍历
matrix
并打印每个元素:
- 可以使用多层循环来遍历嵌套列表。例如,遍历
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for row in matrix:
for element in row:
print(element, end = " ")
print()
- 上述代码首先遍历
matrix
的每一行(子列表),然后在每一行中遍历每个元素并打印,每个元素之间用空格分隔,每行结束后换行。
列表推导式与列表值操作
- 列表推导式基础
- 列表推导式是一种简洁的创建列表的方式,它可以基于现有列表或其他可迭代对象快速生成新列表。基本语法为
[expression for item in iterable if condition]
,其中expression
是对item
进行操作后生成的新元素,for item in iterable
用于遍历可迭代对象中的每个item
,if condition
是可选的过滤条件,只有满足条件的item
才会被用于生成新列表。例如,生成一个包含 1 到 10 中所有偶数的平方的列表:
- 列表推导式是一种简洁的创建列表的方式,它可以基于现有列表或其他可迭代对象快速生成新列表。基本语法为
squares_of_evens = [i**2 for i in range(1, 11) if i % 2 == 0]
print(squares_of_evens) # 输出 [4, 16, 36, 64, 100]
- 结合列表值操作
- 列表推导式可以与列表的各种值操作结合使用。例如,假设有一个包含字符串的列表,我们想过滤掉长度小于 3 的字符串,并将剩余字符串转换为大写:
string_list = ['apple', 'pear', 'a', 'banana']
new_list = [s.upper() for s in string_list if len(s) >= 3]
print(new_list) # 输出 ['APPLE', 'PEAR', 'BANANA']
- 还可以使用嵌套的列表推导式来处理嵌套列表。例如,将二维列表
matrix
展平为一维列表:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened_list = [element for row in matrix for element in row]
print(flattened_list) # 输出 [1, 2, 3, 4, 5, 6, 7, 8, 9]
这里外层的 for row in matrix
遍历二维列表的每一行,内层的 for element in row
遍历每一行中的元素,最终将所有元素收集到一个一维列表中。
列表值与函数和方法的高级应用
- 使用
map()
函数与列表值map()
函数可以对列表中的每个元素应用一个函数,并返回一个新的可迭代对象(Python 3 中需要使用list()
转换为列表)。例如,有一个包含数字字符串的列表,我们想将每个字符串转换为整数:
str_num_list = ['1', '2', '3']
int_num_list = list(map(int, str_num_list))
print(int_num_list) # 输出 [1, 2, 3]
map()
函数也可以与自定义函数一起使用。例如,定义一个将数字平方的函数,然后对列表中的每个元素应用该函数:
def square(x):
return x * x
num_list = [1, 2, 3]
squared_list = list(map(square, num_list))
print(squared_list) # 输出 [1, 4, 9]
- 使用
filter()
函数与列表值filter()
函数用于过滤列表中的元素,根据指定的过滤函数返回一个新的可迭代对象(同样在 Python 3 中需要用list()
转换为列表)。例如,过滤出列表中的偶数:
num_list = [1, 2, 3, 4, 5]
evens = list(filter(lambda x: x % 2 == 0, num_list))
print(evens) # 输出 [2, 4]
- 这里使用了匿名函数
lambda
作为过滤条件,也可以使用自定义函数。例如:
def is_even(x):
return x % 2 == 0
num_list = [1, 2, 3, 4, 5]
evens = list(filter(is_even, num_list))
print(evens) # 输出 [2, 4]
- 使用
reduce()
函数与列表值(Python 3 需从functools
导入)reduce()
函数用于对列表中的元素进行累积操作。在 Python 3 中,需要从functools
模块导入。例如,计算列表中所有元素的乘积:
from functools import reduce
num_list = [1, 2, 3, 4]
product = reduce(lambda x, y: x * y, num_list)
print(product) # 输出 24
- 这里
reduce()
函数从列表的第一个元素开始,依次将当前累积结果和下一个元素作为参数传递给lambda
函数,不断更新累积结果,最终得到所有元素的乘积。
列表值的内存管理与性能优化
- 列表的内存分配
- Python 列表在内存中是以动态数组的形式存储的。当创建一个列表时,Python 会分配一定的内存空间来存储列表元素。随着列表元素的增加,如果当前分配的内存空间不足,Python 会重新分配更大的内存空间,并将原列表的元素复制到新的内存空间中。例如,在不断使用
append()
方法添加元素时,这种内存重新分配和复制操作会发生。 - 了解这一点对于优化性能很重要,因为频繁的内存重新分配和复制操作会带来额外的开销。
- Python 列表在内存中是以动态数组的形式存储的。当创建一个列表时,Python 会分配一定的内存空间来存储列表元素。随着列表元素的增加,如果当前分配的内存空间不足,Python 会重新分配更大的内存空间,并将原列表的元素复制到新的内存空间中。例如,在不断使用
- 性能优化建议
- 预先分配足够空间:如果知道列表最终的大致大小,可以预先分配足够的空间,避免频繁的内存重新分配。例如,使用
[None] * n
创建一个包含n
个None
值的列表,然后再根据需要替换这些值。
- 预先分配足够空间:如果知道列表最终的大致大小,可以预先分配足够的空间,避免频繁的内存重新分配。例如,使用
n = 1000
my_list = [None] * n
for i in range(n):
my_list[i] = i
- 避免不必要的操作:尽量减少在循环中对列表进行
append()
或insert()
等可能导致内存重新分配的操作。如果可以,在循环外准备好数据,然后一次性使用extend()
方法添加到列表中。例如:
data_to_add = []
for i in range(100):
data_to_add.append(i * 2)
my_list = []
my_list.extend(data_to_add)
- 使用更高效的数据结构:在某些情况下,列表可能不是最佳的数据结构。例如,如果需要频繁地在列表头部插入或删除元素,
collections.deque
可能是更好的选择,因为它在两端操作的时间复杂度为 O(1),而列表在头部插入或删除元素的时间复杂度为 O(n)。
from collections import deque
dq = deque()
dq.appendleft(1) # 在头部添加元素
dq.popleft() # 从头部删除元素
通过对 Python 列表值的深入理解和灵活运用,我们可以编写出更高效、简洁且功能强大的代码,无论是在数据处理、算法实现还是日常编程任务中,都能充分发挥列表这一数据结构的优势。