天天看點

python如何删除對象_Python對象引用和del删除引用

1.首先介紹下python的對象引用

1)Python中不存在傳值調用,一切傳遞的都是對象引用,也可以認為是傳址調用。即Python不允許程式員選擇采用傳值或傳引用。Python參數傳遞采用的是“傳對象引用”的方式。實際上,這種方式相當于傳值和傳引用的一種綜合。如果函數參數收到的是一個可變對象(比如字典或者清單)的引用,就能修改對象的原始值——相當于通過“傳引用”來傳遞對象。如果函數收到的是一個不可變對象(比如數字、字元或者元組)的引用,就不能直接修改原始對象——相當于通過"傳值"來傳遞對象。

2)當複制清單或字典時,就複制了對象清單的引用,如果改變引用的值,則修改了原始的參數。

3)為了簡化記憶體管理,Python通過引用計數機制實作自動垃圾回收功能,Python中的每個對象都有一個引用計數,用來計數該對象在不同場所分别被引用了多少次。每當引用一次Python對象,相應的引用計數就增1,每當消毀一次Python對象,則相應的引用就減1,隻有當引用計數為零時,才真正從記憶體中删除Python對象。

2. 可變對象與不可變對象的概念與分類

Python在heap中配置設定的對象分成2類:

不可變對象(immutable object):Number(int、float、bool、complex)、String、Tuple. 采用等效于“傳引用”的方式。

可變對象(mutable object):List、dictionary.采用等效于“傳值”的方式。

#!/usr/bin/evn python

# -*- coding:utf-8 -*-

# Author: antcolonies

list1 = [1, 2, 3]

list2 = list1

list3 = list1

print('list1=', list1, '\nlist2=', list2, '\nlist3=', list3)

print('id(list1)=', id(list1), '\nid(list2)=', id(list2), '\nid(list3)=', id(list3))

'''

list1= [1, 2, 3]

list2= [1, 2, 3]

list3= [1, 2, 3]

id(list1)= 35456648

id(list2)= 35456648

id(list3)= 35456648

'''

list2 = list2 + [4] # 不可變類型操作

print('list1=', list1, '\nlist2=', list2, '\nlist3=', list3)

print('id(list1)=', id(list1), '\nid(list2)=', id(list2), '\nid(list3)=', id(list3))

'''

list1= [1, 2, 3]

list2= [1, 2, 3, 4]

list3= [1, 2, 3]

id(list1)= 35456648

id(list2)= 35455304

id(list3)= 35456648

'''

'''

>>> var1 = 1

>>> var2 = var1

>>> var1,var2

(1, 1)

>>> id(var1),id(var2) # 位址1782298288的引用為2

(1782298288, 1782298288)

>>> var1 += 1 # 位址1782298288的引用為2-1=1

>>> var1,var2

(2, 1)

>>> id(var1),id(var2)

(1782298320, 1782298288)

>>>

'''

list3 += [4] # 可變類型操作

print('list1=', list1, '\nlist2=', list2, '\nlist3=', list3)

print('id(list1)=', id(list1), '\nid(list2)=', id(list2), '\nid(list3)=', id(list3))

'''

list1= [1, 2, 3, 4]

list2= [1, 2, 3, 4]

list3= [1, 2, 3, 4]

id(list1)= 35456648

id(list2)= 35455304

id(list3)= 35456648

'''

3. del 是删除引用而不是删除對象,對象由自動垃圾回收機制(GC)删除

看這個例子:

>>> x = 1

>>> del x

>>> x

Traceback (most recent call last):

File "", line 1, in

x

NameError: name 'x' is not defined

>>> x = ['Hello','world']

>>> y = x

>>> y

['Hello', 'world']

>>> x

['Hello', 'world']

>>> del x

>>> x

Traceback (most recent call last):

File "", line 1, in

x

NameError: name 'x' is not defined

>>> y

['Hello', 'world']

>>>

可以看到x和y指向同一個清單,但是删除x後,y并沒有受到影響。這是為什麼呢?

The reason for this is that you only delete the name,not the list

itself,In fact ,there is no way to delete values in python(and you don’t

really need to because the python interpreter does it by itself

whenever you don’t use the value anymore)

舉個例子,一個資料(比如例子中的清單),就是一個盒子,我們把它賦給一個變量x,就是好像把一個标簽x貼到了盒子上,然後又貼上了y,用它們來代表這個資料,但是用del删除這個變量x就像是把标有x的标簽給撕了,剩下了y的标簽。

再看一個例子:

shoplist = ['apple', 'mango', 'carrot', 'banana']

print ('The first item I will buy is', shoplist[0])

olditem = shoplist[0]

del shoplist[0] #del的是引用,而不是對象

print ('I bought the',olditem)

print ('My shopping list is now', shoplist)

print(shoplist[0])

結果為:

The first item I will buy is apple

I bought the apple

My shopping list is now ['mango', 'carrot', 'banana']

mango

執行個體補充:

#!/usr/bin/evn python

# -*- coding:utf-8 -*-

# Author: antcolonies

'''

python中的内置方法del不同于C語言中的free和C++中的delete

(free和delete直接回收記憶體,當然存儲于該記憶體的對象也就挂了)

Python都是引用,垃圾回收為GC機制

'''

'''

if __name__ == '__main__':

a = 1 # 對象 1 被 變量a引用,對象1的引用計數器為1

b = a # 對象1 被變量b引用,對象1的引用計數器加1

c = a # 對象1 被變量c引用,對象1的引用計數器加1

del a # 删除變量a,解除a對1的引用,對象1的引用計數器減1

del b # 删除變量b,解除b對1的引用,對象1的引用計數器減1

print(c) # 1

'''

if __name__=='__main__':

li=['one','two','three','four','five'] # 清單本身不包含資料'one','two','three','four','five',而是包含變量:li[0] li[1] li[2] li[3] li[4]

first=li[0] # 拷貝清單,也不會有資料對象的複制,而是建立新的變量引用

del li[0]

print(li) # ['two','three','four','five']

print(first) # one

list1 = li

del li

print(list1) # ['two', 'three', 'four', 'five']

# print(type(li)) # NameError: name 'li' is not defined