MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Python列表值的灵活运用

2023-01-204.7k 阅读

Python 列表值的灵活运用

列表基础回顾

在深入探讨列表值的灵活运用之前,先来简单回顾一下 Python 列表的基础知识。列表是 Python 中最常用的数据结构之一,它是一个有序的可变序列,可以容纳不同类型的元素。通过方括号 [] 来创建列表,元素之间用逗号 , 分隔。例如:

my_list = [1, 'hello', 3.14, True]

这里 my_list 包含了整数、字符串、浮点数和布尔值四种不同类型的元素。列表的索引从 0 开始,我们可以通过索引来访问列表中的元素。例如,要访问 my_list 中的字符串 'hello',可以使用 my_list[1]

列表值的访问与修改

  1. 单个元素访问与修改
    • 访问单个元素时,如上述通过索引获取列表中的元素。而修改单个元素也非常简单,直接通过索引赋值即可。例如:
my_list = [1, 2, 3]
print(my_list[1])  # 输出 2
my_list[1] = 20
print(my_list)  # 输出 [1, 20, 3]
  1. 切片访问与修改
    • 切片是 Python 中访问列表部分元素的强大方式。切片语法为 list[start:stop:step]start 是起始索引(包含),stop 是结束索引(不包含),step 是步长,默认值分别为 0、列表长度和 1。例如:
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]

列表值的添加与删除

  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]
  1. 删除元素
    • 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]

列表值的查找与计数

  1. 查找元素
    • 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
  1. 计数元素
    • count() 方法:用于统计列表中某个元素出现的次数。例如:
my_list = [1, 2, 2, 3]
count = my_list.count(2)
print(count)  # 输出 2

列表值的排序与反转

  1. 排序
    • 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]
  1. 反转
    • 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]

列表值的嵌套

  1. 创建嵌套列表
    • 列表可以包含其他列表,形成嵌套结构。例如,创建一个二维列表:
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
  1. 修改嵌套列表的值
    • 同样通过多层索引来修改嵌套列表中的元素。例如,将 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]]
  1. 遍历嵌套列表
    • 可以使用多层循环来遍历嵌套列表。例如,遍历 matrix 并打印每个元素:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for row in matrix:
    for element in row:
        print(element, end = " ")
    print()
  • 上述代码首先遍历 matrix 的每一行(子列表),然后在每一行中遍历每个元素并打印,每个元素之间用空格分隔,每行结束后换行。

列表推导式与列表值操作

  1. 列表推导式基础
    • 列表推导式是一种简洁的创建列表的方式,它可以基于现有列表或其他可迭代对象快速生成新列表。基本语法为 [expression for item in iterable if condition],其中 expression 是对 item 进行操作后生成的新元素,for item in iterable 用于遍历可迭代对象中的每个 itemif 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]
  1. 结合列表值操作
    • 列表推导式可以与列表的各种值操作结合使用。例如,假设有一个包含字符串的列表,我们想过滤掉长度小于 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 遍历每一行中的元素,最终将所有元素收集到一个一维列表中。

列表值与函数和方法的高级应用

  1. 使用 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]
  1. 使用 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]
  1. 使用 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 函数,不断更新累积结果,最终得到所有元素的乘积。

列表值的内存管理与性能优化

  1. 列表的内存分配
    • Python 列表在内存中是以动态数组的形式存储的。当创建一个列表时,Python 会分配一定的内存空间来存储列表元素。随着列表元素的增加,如果当前分配的内存空间不足,Python 会重新分配更大的内存空间,并将原列表的元素复制到新的内存空间中。例如,在不断使用 append() 方法添加元素时,这种内存重新分配和复制操作会发生。
    • 了解这一点对于优化性能很重要,因为频繁的内存重新分配和复制操作会带来额外的开销。
  2. 性能优化建议
    • 预先分配足够空间:如果知道列表最终的大致大小,可以预先分配足够的空间,避免频繁的内存重新分配。例如,使用 [None] * n 创建一个包含 nNone 值的列表,然后再根据需要替换这些值。
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 列表值的深入理解和灵活运用,我们可以编写出更高效、简洁且功能强大的代码,无论是在数据处理、算法实现还是日常编程任务中,都能充分发挥列表这一数据结构的优势。