【Python】S1 基础篇 P2 列表详解:基础操作

发布于:2025-09-08 ⋅ 阅读:(24) ⋅ 点赞:(0)

在这里插入图片描述

列表是什么

列表(list)由一系列按特定顺序排列的元素组成的有序集合。作为一种有序、可变的容器类型,列表能够存储任意类型的对象,并支持丰富的操作方法。列表具有以下特点:

  • 有序性: 元素按照插入顺序排列,具有固定的索引位置
  • 可变性: 创建后可以修改、添加和删除元素
  • 异构性: 可以存储不同类型的数据(字符串、数字、对象等)
  • 动态性: 长度可以根据需要动态调整

列表的创建与表示

在 Python 中,用方括号 [] 表示列表,用逗号分隔其中的元素。

# 创建包含字符串的列表
programming_languages = ['Python', 'Java', 'JavaScript', 'C++']
print(programming_languages)
# 输出:['Python', 'Java', 'JavaScript', 'C++']

# 创建混合类型列表
mixed_data = ['Python', 3.9, True, None]
print(mixed_data)
# 输出:['Python', 3.9, True, None]

列表元素访问与索引

基本索引操作

列表中的每个元素都有一个唯一的索引位置。Python使用零基索引(zero-based indexing),即第一个元素的索引为0:

fruits = ['apple', 'banana', 'orange', 'grape']

# 访问第一个元素
print(fruits[0])    # 输出:apple

# 访问第三个元素
print(fruits[2])    # 输出:orange

# 访问最后一个元素
print(fruits[3])    # 输出:grape

负索引的高级用法

列表提供了负索引功能,允许从列表末尾开始计数:

fruits = ['apple', 'banana', 'orange', 'grape']

print(fruits[-1])   # 输出:grape(最后一个元素)
print(fruits[-2])   # 输出:orange(倒数第二个元素)
print(fruits[-4])   # 输出:apple(倒数第四个元素,即第一个元素)

技术要点:负索引的计算公式为 负索引 = 列表长度 - 正索引,这种设计简化了对列表尾部元素的访问操作。


修改、添加和删除列表元素

相比后续博文会跟读者们介绍的元组不同,列表是动态、可修改的。这意味着列表在创建后,将随着程序的运行增删元素。

修改列表元素

列表的可变性允许直接通过索引修改元素值:

vehicles = ['Tesla', 'BMW', 'Mercedes', 'Audi']
print(f"修改前:{vehicles}")

# 修改第二个元素
vehicles[1] = 'Volvo'
print(f"修改后:{vehicles}")
# 输出:['Tesla', 'Volvo', 'Mercedes', 'Audi']

在列表中添加元素

append():末尾添加元素

append() 方法是最常用的添加元素方法,将新元素添加到列表末尾:

technologies = ['Python', 'Django']
technologies.append('Flask')
technologies.append('FastAPI')
print(technologies)  # 输出:['Python', 'Django', 'Flask', 'FastAPI']

性能特点:append() 操作的时间复杂度为 O ( 1 ) O(1) O(1),具有很高的执行效率。

insert():指定位置插入元素

insert() 方法可以在列表的任意位置插入新元素:

colors = ['red', 'blue', 'green']
colors.insert(1, 'yellow')  # 在索引1的位置插入'yellow'
print(colors)  # 输出:['red', 'yellow', 'blue', 'green']

# 在列表开头插入
colors.insert(0, 'purple')
print(colors)  # 输出:['purple', 'red', 'yellow', 'blue', 'green']

技术要点:insert() 操作的时间复杂度为 O ( n ) O(n) O(n),因为需要移动插入位置之后的所有元素。

extend():批量添加元素

extend() 方法用于将另一个可迭代对象的所有元素添加到列表末尾:

list1 = [1, 2, 3]
list2 = [4, 5, 6]

# 使用extend()
list1.extend(list2)
print(list1)  # 输出:[1, 2, 3, 4, 5, 6]

# 也可以扩展其他可迭代对象
list1.extend('abc')
print(list1)  # 输出:[1, 2, 3, 4, 5, 6, 'a', 'b', 'c']

列表元素的删除操作

del语句:按索引删除

del 语句可以删除指定索引位置的元素或切片:

animals = ['cat', 'dog', 'rabbit', 'hamster', 'fish']

# 删除单个元素
del animals[1]  # 删除'dog'
print(animals)  # 输出:['cat', 'rabbit', 'hamster', 'fish']

pop():弹出元素并返回

pop() 方法删除并返回指定位置的元素,默认删除最后一个元素:

stack = ['item1', 'item2', 'item3', 'item4']

# 弹出最后一个元素
last_item = stack.pop()
print(f"弹出的元素:{last_item}")  # 输出:item4
print(f"剩余元素:{stack}")        # 输出:['item1', 'item2', 'item3']

# 弹出指定位置的元素
first_item = stack.pop(0)
print(f"弹出的元素:{first_item}")  # 输出:item1
print(f"剩余元素:{stack}")         # 输出:['item2', 'item3']

使用场景:pop() 特别适合实现栈(Stack)和队列(Queue)等数据结构。

remove():按值删除

remove() 方法删除列表中第一次出现的指定值:

numbers = [1, 2, 3, 2, 4, 2, 5]
numbers.remove(2)  # 只删除第一个2
print(numbers)     # 输出:[1, 3, 2, 4, 2, 5]

# 删除所有指定值的安全方法
def remove_all(lst, value):
    while value in lst:
        lst.remove(value)

remove_all(numbers, 2)
print(numbers)  # 输出:[1, 3, 4, 5]

clear():清空列表

clear() 方法删除列表中的所有元素:

temp_list = [1, 2, 3, 4, 5]
temp_list.clear()
print(temp_list)  # 输出:[]

删除方法的选择策略

删除方法选择指南:

  1. 知道索引位置且不需要返回值 → 使用 del
  2. 知道索引位置且需要返回值 → 使用 pop()
  3. 知道元素值但不知道位置 → 使用 remove()
  4. 需要删除所有元素 → 使用 clear()

列表的排序与组织

sort():永久排序

sort() 方法直接修改原列表,实现永久排序:

# 字符串列表排序
fruits = ['banana', 'apple', 'cherry', 'date']
fruits.sort()
print(fruits)  # 输出:['apple', 'banana', 'cherry', 'date']

# 反向排序
fruits.sort(reverse=True)
print(fruits)  # 输出:['date', 'cherry', 'banana', 'apple']

# 数字列表排序
numbers = [64, 34, 25, 12, 22, 11, 90]
numbers.sort()
print(numbers)  # 输出:[11, 12, 22, 25, 34, 64, 90]

sorted():临时排序

sorted() 函数返回排序后的新列表,不修改原列表:

original = ['zebra', 'ant', 'bear', 'cat']
sorted_list = sorted(original)

print(f"原列表:{original}")      # 输出:['zebra', 'ant', 'bear', 'cat']
print(f"排序后:{sorted_list}")   # 输出:['ant', 'bear', 'cat', 'zebra']

# 反向排序
reverse_sorted = sorted(original, reverse=True)
print(f"反向排序:{reverse_sorted}")  # 输出:['zebra', 'cat', 'bear', 'ant']

自定义排序规则

使用 key 参数实现复杂排序逻辑:

# 按字符串长度排序
words = ['python', 'java', 'c', 'javascript', 'go']
words_by_length = sorted(words, key=len)
print(words_by_length)  # 输出:['c', 'go', 'java', 'python', 'javascript']

# 按绝对值排序
numbers = [-5, 2, -1, 4, -3]
sorted_by_abs = sorted(numbers, key=abs)
print(sorted_by_abs)  # 输出:[-1, 2, -3, 4, -5]

# 复杂对象排序
students = [
    {'name': 'Alice', 'score': 85},
    {'name': 'Bob', 'score': 90},
    {'name': 'Charlie', 'score': 78}
]
students_by_score = sorted(students, key=lambda x: x['score'], reverse=True)
print(students_by_score)

reverse():反转列表

reverse() 方法反转列表中元素的顺序:

numbers = [1, 2, 3, 4, 5]
numbers.reverse()
print(numbers)  # 输出:[5, 4, 3, 2, 1]

# 或者使用切片实现反转(不修改原列表)
original = [1, 2, 3, 4, 5]
reversed_copy = original[::-1]
print(f"原列表:{original}")       # 输出:[1, 2, 3, 4, 5]
print(f"反转副本:{reversed_copy}") # 输出:[5, 4, 3, 2, 1]

列表的查询与统计

len():获取列表长度

colors = ['red', 'green', 'blue', 'yellow']
print(f"列表长度:{len(colors)}")  # 输出:4

# 空列表的长度
empty_list = []
print(f"空列表长度:{len(empty_list)}")  # 输出:0

in和not in:成员检查

fruits = ['apple', 'banana', 'orange']

# 检查元素是否存在
if 'apple' in fruits:
    print("找到苹果!")

if 'grape' not in fruits:
    print("没有葡萄")

# 在条件表达式中使用
status = "存在" if 'banana' in fruits else "不存在"
print(f"香蕉{status}")

count():统计元素出现次数

numbers = [1, 2, 2, 3, 2, 4, 2, 5]
count_of_2 = numbers.count(2)
print(f"数字2出现了{count_of_2}次")  # 输出:4次

index():查找元素索引

animals = ['cat', 'dog', 'rabbit', 'dog', 'fish']

# 查找第一次出现的位置
dog_index = animals.index('dog')
print(f"狗第一次出现在索引:{dog_index}")  # 输出:1

# 在指定范围内查找
try:
    second_dog_index = animals.index('dog', dog_index + 1)
    print(f"狗第二次出现在索引:{second_dog_index}")  # 输出:3
except ValueError:
    print("未找到更多的狗")

高级列表操作技巧(选)

若读者不具备 for 等循环以及 if 等判断基础,建议跳过。

列表推导式

列表推导式提供了创建列表的简洁语法:

# 基本列表推导式
squares = [x**2 for x in range(10)]
print(squares)  # 输出:[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 带条件的列表推导式
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)  # 输出:[0, 4, 16, 36, 64]

# 复杂表达式
words = ['hello', 'world', 'python', 'programming']
capitalized = [word.upper() for word in words if len(word) > 5]
print(capitalized)  # 输出:['PYTHON', 'PROGRAMMING']

多维列表

# 创建二维列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# 访问元素
print(matrix[1][2])  # 输出:6(第二行第三列)

# 使用列表推导式创建二维列表
matrix_2d = [[i*3 + j + 1 for j in range(3)] for i in range(3)]
print(matrix_2d)  # 输出:[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

列表的拷贝

浅拷贝与深拷贝:
浅拷贝复制对象本身,但不复制对象中的子对象,子对象在原对象和副本之间共享。深拷贝则复制对象及其所有子对象,原对象和副本完全独立。

original = [1, 2, [3, 4], 5]

# 浅拷贝
shallow_copy1 = original.copy()
shallow_copy2 = original[:]
shallow_copy3 = list(original)

# 深拷贝
import copy
deep_copy = copy.deepcopy(original)

# 验证拷贝效果
original[2].append(999)
print(f"原列表:{original}")      # [1, 2, [3, 4, 999], 5]
print(f"浅拷贝:{shallow_copy1}") # [1, 2, [3, 4, 999], 5]
print(f"深拷贝:{deep_copy}")     # [1, 2, [3, 4], 5]

性能优化与最佳实践(选)

初学者,暂可做兴趣了解,性能等内容并非初期所应考虑,但可扩展了解,建立概念体系。

时间复杂度分析

# 不同操作的时间复杂度
performance_guide = {
    'append()': 'O(1) - 非常快',
    'insert(0, x)': 'O(n) - 在开头插入较慢',
    'insert(i, x)': 'O(n) - 中间插入较慢',
    'pop()': 'O(1) - 删除末尾元素很快',
    'pop(0)': 'O(n) - 删除开头元素较慢',
    'del list[i]': 'O(n) - 删除中间元素较慢',
    'remove(x)': 'O(n) - 需要搜索元素位置',
    'in/not in': 'O(n) - 需要遍历列表',
    'len()': 'O(1) - 非常快'
}

内存优化技巧

# 使用生成器表达式减少内存占用
# 对于大数据集,优先考虑生成器
large_data = (x**2 for x in range(1000000))  # 生成器,惰性求值

# 及时删除不需要的大列表
big_list = list(range(1000000))
# ... 使用big_list
del big_list  # 显式删除,释放内存

# 使用切片时注意内存拷贝
original = list(range(1000))
# 这会创建新的列表,占用额外内存
partial = original[100:200]

常见错误与调试技巧

索引错误处理

def safe_get_element(lst, index, default=None):
    """安全获取列表元素,避免索引错误"""
    try:
        return lst[index]
    except IndexError:
        return default

# 使用示例
my_list = [1, 2, 3]
print(safe_get_element(my_list, 5, "不存在"))  # 输出:不存在

避免修改迭代中的列表

迭代修改列表会导致索引混乱,出现元素跳过甚至可能出现无限循环的情况。

# 错误做法:在迭代时修改列表
numbers = [1, 2, 3, 4, 5, 6]
# for num in numbers:  # 这样会导致问题
#     if num % 2 == 0:
#         numbers.remove(num)

# 正确做法1:反向迭代
for i in range(len(numbers) - 1, -1, -1):
    if numbers[i] % 2 == 0:
        del numbers[i]

# 正确做法2:创建新列表
numbers = [1, 2, 3, 4, 5, 6]
numbers = [num for num in numbers if num % 2 != 0]
print(numbers)  # 输出:[1, 3, 5]

问题本质与演示

当你在使用for循环遍历列表时,Python内部维护着一个迭代器索引来跟踪当前遍历到的位置。如果在遍历过程中修改了列表(添加、删除元素),就会导致索引与实际元素位置不匹配,从而产生意想不到的结果。

# 问题代码:想要删除所有偶数
numbers = [1, 2, 3, 4, 5, 6, 8, 10]
print(f"原始列表:{numbers}")

for num in numbers:
    print(f"当前处理:{num}")
    if num % 2 == 0:  # 如果是偶数就删除
        numbers.remove(num)
        print(f"删除了 {num},当前列表:{numbers}")

print(f"最终结果:{numbers}")

运行结果:

原始列表:[1, 2, 3, 4, 5, 6, 8, 10]
当前处理:1
当前处理:2
删除了 2,当前列表:[1, 3, 4, 5, 6, 8, 10]
当前处理:4
删除了 4,当前列表:[1, 3, 5, 6, 8, 10]
当前处理:6
删除了 6,当前列表:[1, 3, 5, 8, 10]
当前处理:10
删除了 10,当前列表:[1, 3, 5, 8]
最终结果:[1, 3, 5, 8]

总结

Python列表作为最基础且强大的数据结构,在日常编程中扮演着核心角色。通过本博文的深入展开,我们涵盖了列表的以下关键知识点:

  • 基础概念: 列表的定义、特性和创建方法
  • 访问操作: 索引、负索引等访问技巧
  • 修改操作: 单元素修改和批量修改方法
  • 增删操作: append、insert、extend、del、pop、remove等方法的使用场景
  • 排序组织: sort、sorted、reverse等排序和组织方法
  • 查询统计: len、in、count、index等查询方法
  • 高级技巧: 列表推导式、多维列表、拷贝机制
  • 性能优化: 时间复杂度分析和最佳实践

掌握这些列表操作不仅能提高编程效率,更是深入学习Python其他高级特性的重要基础。在实际项目中,合理选择列表操作方法,注意性能优化,能够编写出更加高效和优雅的Python代码。


2025.09 西直门


网站公告

今日签到

点亮在社区的每一天
去签到