流暢的python 第 8章: 對象引用、可變性和垃圾回收

1. 標識、相等性和別名

變量a和b是否是同一個值的引用, 可以用 is 來進行判斷:

>>> a = b = [4,5,6]
>>> c = [4,5,6]
>>> a is b
True
>>> x is c
False

如果兩個變量都是指向同一個對象, 我們通常會說變量是另一個變量的 別名 .


在==和is之間選擇

運算符 == 是用來判斷兩個對象的值是否相等(注意是對象值). 而 is 則是用於判斷兩個變量是否指向同一個對象, 或者說判斷變量是不是同一個別名, is 並不關心對象的值. 從使用上, == 使用比較多, 而 is 的執行速度比較快.



2. 淺拷貝深拷貝


 淺拷貝:拷貝出的新的對象,並引用源對象的一切

 >>> import copy
>>> a = {1: [1,2,3]}
>>> b = a.copy()
>>> a,b,
({1: [1, 2, 3]}, {1: [1, 2, 3]})
>>> a[1].remove(3)
>>> a,b
({1: [1, 2]}, {1: [1, 2]})
>>> 


深拷貝:遞歸地拷貝源對象中的一切。(徹頭徹尾的另立門戶)
>>> import copy
>>> c = copy.deepcopy(a)
>>> a,c
({1: [1, 2]}, {1: [1, 2]})
>>> a[1].append(3)
>>> a,c
({1: [1, 2, 3]}, {1: [1, 2]})
>>> 




3. 函數的參數做引用時

python中的函數參數都是採用共享傳參. 共享傳參指函數的各個形式參數獲得實參中各個引用的副本. 也就是說, 函數內部的形參

是實參的別名.

傳入不可變對象無法修改外部的值

>>> def f(a, b):
... a += b
... return a
...

>>> x = 1
>>> y = 2
>>> f(x, y)
3
>>> x, y  
(1, 2)

>>> t = (10, 20)
>>> u = (30, 40)
>>> f(t, u)
(10, 20, 30, 40)
>>> t, u  
((10, 20), (30, 40))

傳入可變對象可以修改外部的值
>>> a = [1, 2]
>>> b = [3, 4]
>>> f(a, b)
[1, 2, 3, 4]
>>> a, b 
([1, 2, 3, 4], [3, 4])



4. 不要使用可變對象作爲函數的默認值

參數默認值是個很棒的特性. 對於開發者來說, 應該避免使用可變對象作爲參數默認值. 因爲如果參數默認值是可變對象, 而且修改了它的內容, 那麼後續的函數調用上都會收到影響,最好是將默認值設爲None。

>>> def f(v,l=[]):
	l.append(v)
	print(id(l))
	return l

>>> f('a')
70125408
['a']
>>> f('b')
70125408
['a', 'b']
>>> 

這種結果應該不是你想要的。爲了避免這種情況的發生,最好是將默認值設爲None,然後在函數裏面檢查它, 

>>> def f(v, l=None):
	if l is None:
		l = []
	l.append(v)
	print(id(l))
	return l

>>> f('a')
70125808
['a']
>>> f('b')
70124808
['b']
>>> 



5. del 和垃圾回收


del 語句刪除名稱,而不是對象。 del 命令可能會導致對象被當作垃圾回收,但是僅當刪除
的變量保存的是對象的最後一個引用,或者無法得到對象時。 2 重新綁定也可能會導致對象
的引用數量歸零,導致對象被銷燬。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章