网站首页 > 基础教程 正文
一、对话引出列表难题
小白的困惑
小白(满脸抓狂):我写了a = [1, 2]和b = a,为什么改b[0]后a也变了?这完全不符合我的预期啊!
专家的解答
专家(推了推眼镜,耐心解释):在 Python 中,列表是可变对象。当你使用b = a这样的直接赋值时,实际上是进行了引用拷贝,a和b指向的是同一个列表对象。所以,对b的任何修改,都会直接反映在a上。若你想要一个独立的副本,必须使用copy()方法或者切片操作。比如b = a.copy()或者b = a[:],这样b就会拥有属于自己的独立数据,修改b不会影响到a 。
二、列表基础三连击
(一)创建与索引
# 标准创建
nums = [1, 2, 3]
mix_list = [1, "文本", True]
# 迷惑操作
wrong_list = [1, 2, ] # 尾随逗号合法但危险!
empty_list = [] # 空列表要这样写
# 索引切片
print(nums[1]) # → 2
print(nums[-1]) # → 3
print(nums[1:]) # → [2, 3](左闭右开)
- 标准创建:可以创建包含单一类型元素的列表,如nums,也能创建包含不同类型元素的混合列表,像mix_list。
- 迷惑操作:虽然 Python 允许在列表元素后添加尾随逗号,但这在多数情况下没有实际意义,还可能引发代码阅读和维护的混淆,所以尽量避免。创建空列表直接使用[]即可。
- 索引切片:列表索引从 0 开始,nums[1]获取第二个元素;nums[-1]获取最后一个元素;切片操作nums[1:]生成一个从索引 1 开始到列表末尾的新列表,遵循左闭右开原则。
专家提醒:务必牢记列表索引从 0 开始,切片操作会生成新列表,这在实际编程中非常关键,能避免许多不必要的错误 。
(二)增删改查核心操作
# 添加元素
nums.append(4) # → [1,2,3,4]
nums.insert(1, 9) # → [1,9,2,3,4]
# 删除元素
nums.remove(9) # 删除第一个匹配值
del nums[0] # 删除索引位置元素
# 修改元素
nums[1] = 99 # → [2,99,3,4]
- 添加元素:append()方法在列表末尾添加一个元素;insert()方法可以在指定索引位置插入元素。
- 删除元素:remove()方法删除列表中第一个匹配的元素;del语句可以删除指定索引位置的元素。
- 修改元素:直接通过索引赋值即可修改列表中对应位置的元素。
您可以想象列表像一列火车车厢,添加元素如同在火车末尾挂接新的车厢(append),或者在中间某个位置插入车厢(insert);删除元素则类似拆卸车厢,remove是拆掉第一个符合条件的车厢,del是按位置拆掉指定车厢;修改元素就像是给某个车厢重新装修 。
三、常用函数火力全开
(一)合并与扩展
a = [1, 2]
b = [3, 4]
print(a + b) # → [1,2,3,4](新建列表)
a.extend(b) # → [1,2,3,4](原地扩展)
# 经典错误
a.append(b) # → [1,2,[3,4]](嵌套列表)
- +运算符合并:使用+运算符会创建一个新的列表,将两个列表的元素依次合并进去。
- extend()方法扩展:extend()方法则是在原列表的基础上进行扩展,直接修改原列表,不会创建新的列表对象。
- 经典错误:append()方法是将传入的参数作为一个整体添加到列表末尾,所以a.append(b)会导致b作为一个子列表被添加到a中,形成嵌套列表,这往往不是我们想要的结果。
(二)排序与反转
nums = [3,1,4,2]
nums.sort() # → [1,2,3,4](原地排序)
sorted_nums = sorted(nums, reverse=True) # → [4,3,2,1](新建列表)
nums.reverse() # → [2,4,1,3](原地反转)
- sort()方法排序:sort()方法会对列表进行原地排序,直接修改原列表,使其元素按升序排列。
- sorted()函数排序:sorted()函数会返回一个新的已排序的列表,原列表保持不变。通过设置reverse=True,可以实现降序排序。
- reverse()方法反转:reverse()方法将列表中的元素顺序进行原地反转。
(三)列表推导式
# 传统写法
squares = []
for x in range(5):
squares.append(x**2)
# 推导式写法
squares = [x**2 for x in range(5)] # → [0,1,4,9,16]
# 带条件筛选
even_squares = [x**2 for x in range(10) if x%2==0]
- 传统写法:通过循环遍历,依次计算每个数的平方并添加到列表中。
- 推导式写法:列表推导式提供了一种简洁的方式来创建列表。[x**2 for x in range(5)]这一行代码就实现了与传统循环相同的功能,代码更加简洁明了。
- 带条件筛选:在推导式中还可以添加条件筛选,[x**2 for x in range(10) if x%2==0]表示只计算 10 以内偶数的平方,并生成列表。
四、高阶函数工具箱
(一)元素定位三剑客
nums = [5, 2, 5, 8, 5]
# 查找元素位置
print(nums.index(5)) # → 0(首个匹配索引)
print(nums.index(5, 1)) # → 2(从索引1开始找)
# 元素计数
print(nums.count(5)) # → 3(出现次数)
# 弹出元素
last = nums.pop() # → 5(默认弹出最后一个)
second = nums.pop(1) # → 2(弹出指定索引)
- index()方法查找位置:index()方法用于查找元素在列表中的索引位置,若找到则返回首个匹配的索引;还可以指定从某个索引位置开始查找。
- count()方法计数:count()方法统计元素在列表中出现的次数。
- pop()方法弹出元素:pop()方法默认弹出并返回列表的最后一个元素;也可以传入索引,弹出指定位置的元素。
(二)列表堆栈与队列
# 栈操作(后进先出)
stack = []
stack.append(1) # 入栈
stack.append(2)
print(stack.pop()) # → 2 出栈
# 队列操作(先进先出)
from collections import deque
queue = deque(["A", "B"])
queue.append("C") # 入队
print(queue.popleft()) # → A 出队
- 栈操作:利用列表的append()和pop()方法,可以模拟栈的后进先出(LIFO)操作。append()实现入栈,pop()实现出栈。
- 队列操作:Python 的collections模块中的deque类可用于实现队列。append()方法用于入队,popleft()方法用于出队,遵循先进先出(FIFO)原则。
五、扩展知识:暗黑技巧
(一)列表解包魔法
# 基本解包
a, b, c = [1, 2, 3] # → a=1, b=2, c=3
# 星号解包
first, *middle, last = [1, 2, 3, 4, 5]
print(middle) # → [2, 3, 4]
# 合并列表
combined = [*[1,2], *[3,4]] # → [1,2,3,4]
- 基本解包:可以将列表中的元素按顺序依次赋值给多个变量,前提是变量数量与列表元素数量一致。
- 星号解包:使用星号(*)可以将列表中的部分元素收集到一个新的列表中。如first, *middle, last = [1, 2, 3, 4, 5],middle会收集中间的元素[2, 3, 4]。
- 合并列表:通过在列表前加星号,可以将多个列表合并成一个新列表,这种方式简洁高效。
(二)列表与生成器的完美结合
# 生成器表达式(处理海量数据)
big_data = (x**2 for x in range(1000000))
sum_result = sum(x for x in big_data if x%10==0)
# 内存对比测试(生成器省内存!)
import sys
print(sys.getsizeof([x for x in range(1000000)])) # → 8448728字节
print(sys.getsizeof(x for x in range(1000000))) # → 208字节
- 生成器表达式:生成器表达式类似于列表推导式,但它不会立即生成一个完整的列表,而是在需要时逐个生成元素,非常适合处理海量数据,能有效节省内存。
- 内存对比测试:通过sys.getsizeof()函数可以看到,生成器表达式占用的内存远远小于列表推导式生成的列表,在处理大数据集时优势明显。
(三)列表排序黑科技
students = [
{"name": "张三", "age": 20},
{"name": "李四", "age": 18}
]
# 单级排序
students.sort(key=lambda x: x["age"])
# 多级排序(先年龄后姓名)
students.sort(key=lambda x: (x["age"], x["name"]))
# 逆序+自定义排序
words = ["apple", "Banana", "cherry"]
words.sort(key=lambda x: x.lower())) # 忽略大小写排序
- 单级排序:对于包含字典的列表,可以使用sort()方法,并通过key参数指定一个函数来确定排序依据。如students.sort(key=lambda x: x["age"]),按学生年龄进行排序。
- 多级排序:可以在key函数中返回一个元组,实现多级排序。students.sort(key=lambda x: (x["age"], x["name"]))先按年龄排序,年龄相同再按姓名排序。
- 逆序 + 自定义排序:通过key函数结合lower()方法,可以实现忽略大小写的排序,同时还能通过设置reverse=True实现逆序。
把数据想象成一副扑克牌,传统排序像是简单地把牌按花色或数字顺序整理;而这里的排序黑科技就像是可以根据多种规则,如先按花色、再按数字,甚至可以特殊处理某些牌(忽略大小写等),对扑克牌进行花式排序 。
六、性能优化秘籍
(一)预分配空间加速
# 低效写法(动态扩容)
result = []
for i in range(10000):
result.append(i)
# 高效写法(预分配)
result = [0] * 10000
for i in range(10000):
result[i] = i
- 低效写法:在循环中不断使用append()方法向空列表中添加元素,列表会频繁进行动态扩容,这会消耗较多时间和内存。
- 高效写法:通过预分配空间,创建一个指定长度的列表(这里用[0] * 10000创建了一个长度为 10000 的列表),然后再按索引赋值,能显著提高效率。
(二)避免循环内重复操作
# 低效写法(每次循环都调用len())
for i in range(len(my_list)):
if my_list[i] == target:
...
# 高效写法(缓存长度)
list_len = len(my_list)
for i in range(list_len):
if my_list[i] == target:
...
- 低效写法:在循环条件中每次都调用len()函数获取列表长度,这是不必要的重复操作,会降低性能。
- 高效写法:先将列表长度缓存到一个变量中,然后在循环中使用该变量,避免了重复计算。
(三)numpy 混合使用(处理数值计算)
import numpy as np
# 列表转numpy数组
py_list = [1, 2, 3]
np_arr = np.array(py_list)
# 向量化运算(比循环快100倍!)
result = np_arr * 2 + 5
- 列表转 numpy 数组:numpy库的array()函数可以将 Python 列表转换为numpy数组。
- 向量化运算:numpy数组支持向量化运算,如np_arr * 2 + 5,这种运算比使用循环逐个处理元素快很多,在处理数值计算时能大幅提升性能。
七、闭坑指南(血泪总结)
浅拷贝陷阱:
a = [[1,2], [3,4]]
b = a.copy() # 浅拷贝
b[0][0] = 99 # a也变成[[99,2], [3,4]]
# 正确解法:
import copy
c = copy.deepcopy(a)
对于嵌套列表,使用copy()方法进行的是浅拷贝,只会复制外层列表,内层列表仍然是引用。所以修改b的内层列表元素,a也会跟着改变。正确做法是使用copy.deepcopy()进行深拷贝,这样能确保c拥有完全独立的数据。
循环中删除元素:
nums = [1,2,3,4]
for x in nums:
if x%2 ==0:
nums.remove(x) # → [1,3] 漏删!
# 正确解法:
nums = [x for x in nums if x%2!=0]
在循环中直接删除列表元素会导致索引混乱,从而出现漏删的情况。如上述代码,nums中偶数4就会被漏删。推荐使用列表推导式来筛选需要保留的元素,创建一个新的列表。
默认参数可变对象:
def add_item(item, lst=[]):
lst.append(item)
return lst
print(add_item(1)) # → [1]
print(add_item(2)) # → [1,2] 累积结果!
# 正确解法:
def add_item(item, lst=None):
lst = lst or []
lst.append(item)
return lst
在函数定义中,默认参数lst=[]是一个可变对象。这意味着每次调用函数时,如果不传入新的列表,都会使用同一个默认列表,导致结果累积。正确做法是将默认参数设为 None
小白:(跪了)原来列表还能这么玩!我现在就去重构代码!
专家:(露出欣慰笑容)记住:列表虽好,但数据量大时该用字典或数组!
猜你喜欢
- 2025-03-24 10个非常重要的Python列表方法(python的列表怎么用)
- 2025-03-24 Python编程入门:基本数据类型之列表
- 2025-03-24 python序列之列表详解(python序列类型及运算)
- 2025-03-24 一文掌握在Python列表中添加元素的多种方法
- 2025-03-24 10 非常重要的 Python 列表方法(python 列表常用方法)
- 2025-03-24 Python 基础教程三之Python3 列表
- 2025-03-24 Python的数据结构详解一(列表)(python数据结构教程)
- 2025-03-24 5-4-Python数据类型-列表(python中6种数据类型)
- 2025-03-24 python数据容器之列表、元组、字符串
- 2025-03-24 掌握 Python 列表:综合指南(python入门之玩转列表)
- 最近发表
- 标签列表
-
- jsp (69)
- pythonlist (60)
- gitpush (78)
- gitreset (66)
- python字典 (67)
- dockercp (63)
- gitclone命令 (63)
- dockersave (62)
- linux命令大全 (65)
- mysql教程 (60)
- pythonif (86)
- location.href (69)
- deletesql (62)
- c++模板 (62)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- console.table (62)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)