Python列表是有序、可变的序列,可以存储任意类型的元素。
#- 创建空列表
empty_list = []
empty_list2 = list()
#- 创建包含元素的列表
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True] # 可以混合不同类型
nested = [[1, 2], [3, 4]] # 嵌套列表
print(len(numbers)) # 输出: 5
关键特性:列表是可变的,这意味着我们可以修改、添加、删除元素,这与字符串的不可变性形成对比。
列表的索引和切片操作与字符串类似,但要注意列表是可变的:
fruits = ['apple', 'banana', 'cherry', 'date']
#- 正向索引(从0开始)
print(fruits[0]) # 输出: 'apple'
print(fruits[2]) # 输出: 'cherry'
#- 反向索引(从-1开始)
print(fruits[-1]) # 输出: 'date'
print(fruits[-2]) # 输出: 'cherry'
#- 切片操作
print(fruits[1:3]) # 输出: ['banana', 'cherry']
print(fruits[:2]) # 输出: ['apple', 'banana']
print(fruits[2:]) # 输出: ['cherry', 'date']
常见错误:索引越界会引发IndexError,这是初学者最常遇到的错误之一。
#- 错误示例
#- print(fruits[10]) # IndexError: list index out of range
fruits = ['apple', 'banana']
#- append() - 在末尾添加单个元素
fruits.append('cherry')
print(fruits) # ['apple', 'banana', 'cherry']
#- extend() - 在末尾添加多个元素(合并列表)
fruits.extend(['date', 'elderberry'])
print(fruits) # ['apple', 'banana', 'cherry', 'date', 'elderberry']
#- insert() - 在指定位置插入元素
fruits.insert(1, 'orange')
print(fruits) # ['apple', 'orange', 'banana', 'cherry', 'date', 'elderberry']
#- + 运算符(创建新列表)
new_fruits = fruits + ['fig', 'grape']
print(new_fruits) # 新列表,原列表不变
重要区别:append()和extend()的区别是初学者容易混淆的点。append()将整个对象作为一个元素添加,而extend()会展开可迭代对象。
#- 对比示例
list1 = [1, 2]
list1.append([3, 4]) # 结果是 [1, 2, [3, 4]]
list2 = [1, 2]
list2.extend([3, 4]) # 结果是 [1, 2, 3, 4]
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
#- remove() - 删除第一个匹配的元素
numbers.remove(3) # 删除值为3的元素
print(numbers) # [1, 2, 4, 5, 6, 7, 8]
#- pop() - 删除指定位置的元素并返回
removed = numbers.pop(2) # 删除索引为2的元素
print(removed) # 4
print(numbers) # [1, 2, 5, 6, 7, 8]
#- del语句 - 删除指定位置或切片
del numbers[0] # 删除第一个元素
print(numbers) # [2, 5, 6, 7, 8]
del numbers[1:3] # 删除切片
print(numbers) # [2, 7, 8]
#- clear() - 清空列表
numbers.clear()
print(numbers) # []
fruits = ['apple', 'banana', 'cherry']
#- 直接通过索引修改
fruits[1] = 'orange'
print(fruits) # ['apple', 'orange', 'cherry']
#- 通过切片批量修改
fruits[0:2] = ['pear', 'grape']
print(fruits) # ['pear', 'grape', 'cherry']
#- 注意:切片赋值可以改变列表长度
fruits[1:2] = ['a', 'b', 'c']
print(fruits) # ['pear', 'a', 'b', 'c', 'cherry']
fruits = ['apple', 'banana', 'cherry', 'apple']
#- in 运算符判断元素是否存在
print('banana' in fruits) # True
print('orange' in fruits) # False
#- index() 查找元素第一次出现的索引
print(fruits.index('banana')) # 1
#- print(fruits.index('orange')) # ValueError: 'orange' is not in list
#- count() 统计元素出现次数
print(fruits.count('apple')) # 2
重要提示:使用index()方法时,如果元素不存在会抛出ValueError,建议先使用in判断或使用try-except处理。
my_list = []
#- 错误方式:直接判断长度是否为0
if len(my_list) == 0:
print("列表为空")
#- 更Pythonic的方式:直接判断列表本身
if not my_list: # 空列表在布尔上下文中为False
print("列表为空")
else:
print("列表不为空")
为什么推荐第二种方式:更简洁、更符合Python风格,而且对于空列表、None、非空列表都能正确处理。
numbers = [3, 1, 4, 1, 5, 9, 2]
#- sort() - 原地排序(修改原列表)
numbers.sort()
print(numbers) # [1, 1, 2, 3, 4, 5, 9]
#- sorted() - 返回新列表(原列表不变)
numbers = [3, 1, 4, 1, 5, 9, 2]
sorted_numbers = sorted(numbers)
print(sorted_numbers) # [1, 1, 2, 3, 4, 5, 9]
print(numbers) # [3, 1, 4, 1, 5, 9, 2](原列表未变)
#- 降序排序
numbers.sort(reverse=True)
print(numbers) # [9, 5, 4, 3, 2, 1, 1]
#- 自定义排序(按字符串长度)
words = ['apple', 'banana', 'cherry', 'date']
words.sort(key=len)
print(words) # ['date', 'apple', 'banana', 'cherry']
#- 浅拷贝(shallow copy)
list1 = [1, 2, [3, 4]]
list2 = list1.copy() # 或 list2 = list1[:]
list2[0] = 10
print(list1) # [1, 2, [3, 4]] - 第一层不受影响
print(list2) # [10, 2, [3, 4]]
#- 修改嵌套列表
list2[2][0] = 99
print(list1) # [1, 2, [99, 4]] - 嵌套列表被修改了!
print(list2) # [10, 2, [99, 4]]
#- 深拷贝(deep copy)
import copy
list3 = copy.deepcopy(list1)
list3[2][0] = 100
print(list1) # [1, 2, [99, 4]] - 原列表不受影响
print(list3) # [1, 2, [100, 4]]
关键理解:浅拷贝只复制第一层,嵌套对象是共享的;深拷贝会递归复制所有层级。对于包含可变对象(如列表、字典)的列表,通常需要使用深拷贝。
列表推导式是Python的语法糖,可以简洁地创建列表:
#- 传统方式
squares = []
for i in range(10):
squares.append(i**2)
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
#- 列表推导式
squares = [i**2 for i in range(10)]
print(squares) # 同上
#- 带条件的推导式
even_squares = [i**2 for i in range(10) if i % 2 == 0]
print(even_squares) # [0, 4, 16, 36, 64]
#- 嵌套循环
pairs = [(x, y) for x in range(3) for y in range(3)]
print(pairs) # [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2), (2,0), (2,1), (2,2)]
#- reverse() - 原地反转
numbers = [1, 2, 3, 4]
numbers.reverse()
print(numbers) # [4, 3, 2, 1]
#- 切片反转(创建新列表)
reversed_numbers = numbers[::-1]
#- copy() - 创建浅拷贝
original = [1, 2, 3]
copy_list = original.copy()
copy_list[0] = 10
print(original) # [1, 2, 3]
print(copy_list) # [10, 2, 3]
问题场景:在循环或条件判断中,错误地判断列表是否为空。
#- 错误示例:直接判断列表长度
my_list = []
if len(my_list) == 0: # 虽然正确,但不Pythonic
pass
#- 正确方式
if not my_list: # 推荐
print("列表为空")
#- 如果列表可能为None,需要额外判断
my_list = None
if my_list is None or not my_list:
print("列表为空或为None")
#- 错误示例:在循环中删除元素
numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
numbers.remove(num) # 这会改变列表长度,导致跳过元素
print(numbers) # 可能不是预期结果
#- 正确方式1:创建副本遍历
for num in numbers[:]: # 遍历副本,修改原列表
if num % 2 == 0:
numbers.remove(num)
#- 正确方式2:使用列表推导式
numbers = [num for num in numbers if num % 2 != 0]
#- 正确方式3:倒序遍历(避免索引错位)
for i in range(len(numbers)-1, -1, -1):
if numbers[i] % 2 == 0:
del numbers[i]
#- 错误示例:使用 * 操作符
matrix = [[0] * 3] * 3 # 看似创建了3x3矩阵
matrix[0][0] = 1
print(matrix) # [[1, 0, 0], [1, 0, 0], [1, 0, 0]] - 所有行都指向同一个列表!
#- 正确方式1:使用列表推导式
matrix = [[0] * 3 for _ in range(3)]
matrix[0][0] = 1
print(matrix) # [[1, 0, 0], [0, 0, 0], [0, 0, 0]]
#- 正确方式2:嵌套循环
matrix = []
for i in range(3):
row = []
for j in range(3):
row.append(0)
matrix.append(row)
▶ 避免频繁使用+拼接列表:使用extend()或列表推导式
▶ 判断元素存在时,in操作符的时间复杂度为O(n),对于大列表考虑使用集合(set)
▶ 大量数据操作时,考虑使用NumPy数组(如果元素类型相同)
#- 方法1:使用set(会打乱顺序)
numbers = [1, 2, 2, 3, 3, 3]
unique = list(set(numbers))
print(unique) # [1, 2, 3](顺序可能改变)
#- 方法2:保持顺序
unique = []
for num in numbers:
if num not in unique:
unique.append(num)
print(unique) # [1, 2, 3]
#- 方法3:使用字典(Python 3.6+保持插入顺序)
unique = list(dict.fromkeys(numbers))
print(unique) # [1, 2, 3]
#- 二维列表转一维
matrix = [[1, 2], [3, 4], [5, 6]]
flat = []
for row in matrix:
flat.extend(row)
print(flat) # [1, 2, 3, 4, 5, 6]
#- 使用列表推导式
flat = [num for row in matrix for num in row]
#- 使用itertools.chain
from itertools import chain
flat = list(chain.from_iterable(matrix))