python基础–del操作
list中remove和del的区别
#remove删除首个符合条件的元素,并不删除特定的索引
l1 = [1,1,1,2,3,4,5,5]
l1.remove(2)
print(l1) #[1, 1, 1, 3, 4, 5, 5]
#del按照索引删除字符
l2 = [1,1,1,2,3,4,5,5]
del l2[2]
print(l2) #[1, 1, 2, 3, 4, 5, 5]
del用法
#del 除可以删除单个元素,还可以删除指定范围内的值和整个对象
l = [1,1,1,2,3,4,5,5]
del l[2:5]
print(l) #[1, 1, 4, 5, 5]
del l
print(l) # NameError: name 'l' is not defined
Python中del和垃圾回收
Python语言默认采用的垃圾回收机制是引用计数法,当一个对象的引用计数为0时, Python的垃圾回收机制就会将对象回收。
del语句作用在变量上,而不是数据对象上。也就是说在python中, del语句删除某个对象时, 并不是直接将该对象在内存中删除, 而是将该对象的引用计数-1。下面还是以例子来说,
li = [1,2,3,4,5] #定义列表,列表本身不包含数据1-5,而是包含变量li[0] li[1] li[2] li[3] li[4]
first = li[0] #这相当于浅拷贝,first指向了li[0]
print(id(li)) #li的地址,例为2376828968620
print(id(li[0])) #其中的li[0]地址为141721836406800
print(id(first)) #first地址141721836406800,说明其与li[0]指向一样
del li[0] #删除li[0],实际是引用计数-1
print(id(li)) #li地址不变,仍为2376828968620
print(id(li[0])) #此时li[0]地址为141721836406832,因为最初指向0的引用-1了,而新的li[0]出现了,该值为2
print(id(first)) #first指向1,所以其地址不变
print(li) #[2, 3, 4, 5]
print(first) #值为1
拓展
最初想详细研究remove和del是因为leetcode上的一道数组问题,leetcode283。使用删除非0元素的思路,remove结果正确,而del结果错误。
class Solution(object):
def moveZeroes(self, nums):
if not nums: return []
for i in range(len(nums)):
if nums[i] == 0:
nums.remove(nums[i])
nums.append(0)
return nums
为什么会这样,以nums=[1,0,0,3]为例。如果为remove,其流程为:
- i==0,nums[0]为1,不为0,到下一个循环;
- i==1,nums[1]为0,为0,remove删除首个符合条件的元素,结果为[1,0,3],添加0后为[1,0,3,0];
- i==2,nums[2]为1,不为0,到下一个循环;
- i==3,nums[3]为0,为0,remove删除首个符合条件的元素,结果为[1,3,0],添加0后为[1,3,0,0]。
for i in range(len(nums)):
if nums[i] == 0:
del nums[i]
nums.append(0)
如果为del,以nums=[1,0,0,3]为例,其流程为:
- i==0,nums[0]为1,不为0,到下一个循环;
- i==1,nums[1]为0,为0,del按索引删除,结果为[1,0,3],添加0后为[1,0,3,0];
- i==2,nums[2]为1,不为0,到下一个循环;
- i==3,nums[3]为0,为0,del按索引删除nums[3],结果为[1,0,3],添加0后为[1,0,3,0]。
不过该题还是建议使用双指针。因为list中remove的时间复杂度为O(n)。