说起编程这回事,增加、修改、查找这些操作咱们用得贼溜,但“删除”这个动作,看着简单,里面的门道可不少。尤其是在 Python 里,你要删个文件、删个列表里的元素、删个字典的键值对,甚至想把某个变量从你的脑子里(不对,是从内存里)“忘掉”,方法多着呢,而且每种都有点自己的小脾气。所以今天就来掰扯掰扯,这python 怎么删除,到底是怎么个删法,有哪些坑,又有哪些招儿。
先来个最直观的,删文件。你想啊,写程序有时候就是得处理文件,生成报告啊,下载东西啊,用完了或者出错了,那些临时文件、垃圾文件就得清理,不然硬盘不得炸了?在 Python 里删文件,最常用的工具箱是 os
模块。里面有个叫 os.remove()
的函数,别看名字简单,功能就是字面意思——删除文件。你得给它一个文件路径,绝对的、相对的都行。比如 os.remove('D:/temp/我的破文件.txt')
或者 os.remove('cache/临时数据.dat')
。用这个的时候,得注意几点:一是文件必须存在,不存在它可要给你脸色看(抛 FileNotFoundError
)。二是得有足够的权限,没权限你文件系统这道坎就过不去。三是如果文件正在被别的程序(或者你自己的程序!)占用着,那也删不动,会报 PermissionError
或 OSError
啥的。所以,删文件前,最好先用 os.path.exists()
判断一下,再用 try...except
把可能出现的异常捕获了,这才是稳妥的做法。
那要是想删目录呢?空目录还好说,os.rmdir('我的空文件夹')
,这个跟 os.remove()
差不多,只能删空的。你要是里面还有点儿东西,哪怕就一个隐藏文件,它也删不掉,跟你撅着嘴说 OSError: [Errno 39] Directory not empty
。这可咋整?难道我要一层一层进去,把里面的文件和子目录都先删干净,再回来删这个父目录?累不累啊!这时候,就得请出 shutil
模块了。shutil
是个更高级的文件操作模块,里面有个大杀器,叫 shutil.rmtree()
。这名字听着就霸气,rmtree
,移除整棵树!给它一个目录路径,它就跟你说拜拜,连带目录里的所有文件和子目录,一锅端。用这个可得十二万分小心,它不问你是不是空的,也不问你里面有啥,执行了就没了,不可逆!就像按下了核弹按钮,boom!所以用 shutil.rmtree()
之前,再三确认,是不是真的要连根拔起。我刚学 Python 的时候,有一次写个脚本清理日志,手一滑,路径写错了,差点把项目的主代码目录给删了,那叫一个魂飞魄散!幸好及时按下了 Ctrl+C。所以啊,文件和目录的删除,尤其是 shutil.rmtree()
,务必谨慎再谨慎。
文件系统的事儿聊完了,再来看看 Python 它自己的世界里,那些数据结构的删除。比如,咱最常用的列表 list
。列表这玩意儿,灵活得很,加元素删元素都是家常便饭。python 怎么删除列表里的东西?方法至少有仨!
第一个,也是最直接的,用 del
关键字。是的,又是它!del
在 Python 里是个非常通用的“删除”标记。用在列表上,你可以按索引删:my_list = [10, 20, 30, 40, 50]
; del my_list[2]
。这一下子就把索引是 2 的那个元素(也就是 30)给删掉了,列表变成了 [10, 20, 40, 50]
。删完后,后面的元素会自动往前补位,所以原来索引 3 的 40 现在变成索引 2 了。你还能用切片一次删多个:del my_list[1:3]
,这下把索引 1 和 2 的元素(原来的 20 和 40)都删了,列表就剩 [10, 50]
了。用 del
按索引删,效率很高,因为列表底层可能是个数组,知道索引直接就能定位到,然后把后面的往前挪。
第二个方法,用列表自己的 .remove()
方法。这个厉害了,它不是按位置删,是按值删!比如 my_list = ['apple', 'banana', 'cherry', 'banana']
; my_list.remove('banana')
。它会在列表里从头开始找,找到第一个匹配 ‘banana’ 的元素就删掉。注意了,是第一个!如果列表里有多个 ‘banana’,比如上面这个例子,执行完第一次 .remove('banana')
后,列表变成 ['apple', 'cherry', 'banana']
,那个在末尾的 ‘banana’ 还留着呢。如果你想删掉所有的 ‘banana’,就得循环着来,但这又引出了一个经典问题:在循环遍历列表的同时删除元素,很容易出问题!因为你删掉一个元素后,列表的长度和后面元素的索引都变了,导致循环可能跳过一些元素,或者访问到不存在的索引。正确的做法是,要么遍历列表的副本进行删除,要么使用列表推导式或生成器表达式来构建一个新列表,过滤掉要删除的元素。
第三个方法,也是列表自己的 .pop()
方法。这个方法既可以按索引删,也可以不指定索引。如果你不给索引,比如 my_list.pop()
,它会删掉列表最后一个元素,而且!而且!它会把这个被删掉的元素返回给你!这可是个非常实用的功能,比如你要把列表当作栈来用,.pop()
就是“出栈”操作。如果你给它一个索引,比如 my_list.pop(1)
,那它就删掉指定索引位置的元素(比如索引 1 的),同样也会把被删掉的元素返回。.pop()
按索引删的效率不如 del my_list[index]
高,因为它需要返回那个元素,可能涉及更多操作,但在你需要同时获取被删元素的时候,它就是首选。
总结一下列表的删除:del
按索引/切片删,直接高效;.remove(值)
按值删,注意重复值和循环删除的问题;.pop(索引)
或 .pop()
按索引或末尾删,并返回被删元素,常用于栈或队列模拟。各有各的用途,得看你具体想干啥。
接着看字典 dict
。字典是键值对的集合,它的删除操作相对列表来说,没那么多花样,但也得知道怎么玩。python 怎么删除字典里的东西?主要也是靠 del
和 .pop()
。
用 del
关键字删字典元素,你得指定键(key):my_dict = {'a': 1, 'b': 2, 'c': 3}
; del my_dict['b']
。这一下子就把键为 ‘b’ 的那个键值对给请出去了。字典就剩 {'a': 1, 'c': 3}
了。跟列表按索引删类似,简单直接。但同样要注意,如果你要删的键不存在,它会毫不客气地抛出 KeyError
异常。所以,删之前最好也用 key in my_dict
或者 my_dict.get(key)
判断一下。
字典也有 .pop()
方法,跟列表的 .pop()
类似,它也需要你指定要删除的键,并且会把被删除键对应的值返回给你:value = my_dict.pop('c')
。执行完这句,my_dict
变成 {'a': 1}
,而 value
的值就是 3。.pop()
方法还有一个贴心的地方,你可以给它传一个可选的默认值作为第二个参数。如果指定的键不存在,它不会报错,而是返回你提供的这个默认值。比如 value = my_dict.pop('z', 'key not found')
,如果 ‘z’ 不在字典里,value
就是 ‘key not found’,这比直接报错要友好多了,尤其是在你不能确定键是否存在的时候。
字典还有一个 .popitem()
方法。这个就有点“随缘”了。在 Python 3.7+ 版本中,字典是有序的,popitem()
会删除并返回字典的最后一个插入的键值对(以元组形式 (key, value)
)。而在更老的版本(Python 3.6 及以前),字典是无序的,popitem()
删哪个就有点随机性了,可能删的是任意一个键值对。所以,如果你想删掉并获取字典里的一个随机元素(或者最新插入的那个,取决于版本),可以用 .popitem()
。
集合 set
的删除就更简单了。集合是无序的,元素唯一。python 怎么删除集合里的元素?它提供了 .remove()
和 .discard()
两个方法,都是按值删。my_set = {1, 2, 3, 4}
; my_set.remove(3)
,集合变成 {1, 2, 4}
。如果你要删的元素不在集合里,.remove()
会报错 KeyError
(虽然叫 KeyError 但用在 set 上)。为了避免报错,可以使用 .discard()
:my_set.discard(5)
。如果 5 在集合里,就删掉;不在,啥事儿都不发生,也不报错,安静得很。集合还有一个 .pop()
方法,因为集合是无序的,pop()
会随机删除并返回集合里的一个元素。如果你只是想清空整个集合,最简单的是 my_set.clear()
。
最后,咱们来说说删变量。哎呀,这个听着好像有点玄乎,变量也能删?当然可以。在 Python 里,变量其实就像一个标签,贴在一个对象上。比如 x = 10
,就是把标签 x
贴在了整数对象 10 上。当你不再需要这个标签,或者想让 Python 把它“忘掉”,就可以用咱们的老朋友 del
关键字:del x
。执行这句后,变量名 x
就不再存在了。你再尝试访问 x
,就会收到 NameError: name 'x' is not defined
的警告。注意,del x
删的不是对象 10 本身,而是变量名 x
和对象 10 之间的那个关联。如果对象 10 还有别的变量名指着它,或者被其他地方引用着,它并不会马上从内存里消失。只有当一个对象没有任何变量名指向它,也没有被其他任何地方引用时,Python 的垃圾回收机制才会考虑把它清理掉,释放内存。所以,del
变量更多的是解除绑定,让这个名字失效。有时候在函数里用完一个超大的数据结构,为了显式地表明我不再需要它,早点解除绑定,可能会对内存管理有点微弱的帮助,但 Python 大多数时候自己管得挺好的,咱们一般不太需要操心这个。不过知道有这么个操作总没坏处。你甚至可以 del
函数、del
模块(虽然不常见,也不推荐在运行时这么干)。
啰里啰嗦说了这么多,从删文件到删变量,python 怎么删除这事儿,看着细碎,但每个地方都有点自己的脾气和用法。文件删除得小心路径和权限,尤其是 shutil.rmtree
,那真是说没就没;列表删除花样多,按索引、按值、按位置出栈,循环删除是个陷阱;字典删除按键来,.pop()
还能捞个返回值,处理键不存在更优雅;集合删除看是不是怕报错,remove
还是 discard
,或者随机来一个 pop
;变量删除就是解除绑定,让名字失效。
你看,简单的“删除”两个字,背后牵扯到文件系统、各种数据结构的特性、甚至 Python 的内存管理机制。所以啊,别小瞧任何一个基本操作,多了解一点,少踩一个坑,写代码才能更踏实,不至于关键时刻掉了链子。下次当你再想在 Python 里扔掉点什么东西的时候,停下来想想,这次我是要python 怎么删除?是用 os.remove
还是 shutil.rmtree
?是 del
列表索引还是 remove
列表值?是 del
字典键还是 pop
字典键?脑子里过一遍这些选项,选对最合适、最安全的那一个。这才是一个合格的 Python 使用者该有的觉悟嘛!
评论(0)