幾個重要的點,還不是很熟悉的地方。
一 引用計數與記憶體回收
1 一切對象都是引用計數的。當分配一個新的名字給一個對象或者將其放入一個容器(列表,元組或者字典)時,該對象的引用計數增加1.
a = 1 #分配新的名字,對象1的引用計數增加1
b = a #分配新的名字,對象1的引用計數增加1 或者b = 1 a,b是對同一個對象的引用
c = []
c.append(a) # 引用計數增加1 或者c.append(1)效果一樣
區分什麼是對象,什麼是對象的引用。對象的引用名字也是一種對象,在python中,一切都是對象。
2 del語句,脫離變數範圍,或者變數被重新定義,都會導致引用計數減少1.
del a
b = 2
c[0] = 2
3 當一個對象的引用計數變為0時,該對象就會在適當的時機被記憶體回收行程回收。
然而當出現相互引用時,似乎兩個對象的計數永遠都不會變為0.雖然兩個對象都無法通過名字訪問,但是計數器並沒有減為0.針對這種情況,Python解譯器會定期運行一個搜尋器,去清除無法訪問的對象。
二 引用和副本
1 對可變對象來說,改變它的一個引用,則它的其他引用都改變了
a = [1,2,3]
b = a
a[0] = -1 # b = [-1,2,3]
a.append(4) # b = [-1,2,3,4]
2 而對於不可變對象來說,改變對象的一個引用事實上是建立一個新對象了,對其他引用沒有影響
a = (1,2,3)
b = a
b = [1,2,3]
此時a是a,b是b
3 淺拷貝與深拷貝
淺拷貝複製建立了一個新對象,但它包含的子項目仍然是原來對象的子項目的引用。
理解兩點
1)複製建立了一個新對象
a = [1,2,[3,4]]
b = a[:] # 淺拷貝 複製了a中元素,但b和a不是同一個對象的引用,b是建立了一個新對象
所以
b.append(100) # a不會受到影響
2) 子項目仍然是原來對象的子項目的引用
b[0] = -1 # a不會改變,子項目是不可變對象,參看上1,2兩點
b[2][0] = -3 # a改變,子項目是可變對象,參看1,2兩點
三 一些技巧
apply()
lambda
map()
zip()
reduce()
filter()