Python學習筆記之動態型別
阿新 • • 發佈:2019-02-17
一 變數、物件和引用
在Python中,變數名和物件是獨立分開的,在賦值的過程中,通過引用將變數索引到相應的物件中。
a='Hello World!'
從概念上講,上述語句的建立至少經過三個過程:
1.闢出一塊記憶體來儲存物件 Hello World。
2.變數名a第一次出現時,建立它
3.通過引用,將a與物件 Hello World連線
二 型別屬於物件
a=123
a='hello world!'
較之C語言中的變數需要先聲明後定義這些約束,Python語言無須對變數的型別做約束,因為實際上型別(type)屬於物件。舉例來說,如上述的兩行程式碼,在C語言中同一個變數名被先後賦予不同型別的資料,這完全不可行,而在Python中之所以可行,並非程式改變了變數a的資料型別和值,而是改變了變數a的引用。a原先是通過引用指向物件123,而後在將其指向物件‘hello world’ 而已。即變數所指的物件是什麼型別,變數就是什麼型別。
三 物件垃圾收集(Garbage-Collected)
a=123
a='hello world!'
a=1.23
在Python中,每當一個變數被賦予新的物件時,之前的物件所佔用的空間就會被回收,物件的引用值在此過程中被逐漸的丟棄。如上述的三行程式碼中,當變數a被賦予‘hello world’時,物件123所佔用的記憶體則自動被回收放入自由記憶體空間。
這就意味著在Python中任意使用物件而不需要對其作任何釋放記憶體空間的考慮,因為Python會自動清除已經不需要使用到的物件的記憶體空間。
四 共享引用
a=123
b=a
a='hello world!'
上述程式碼中的第二行的作用是將變數b指向物件123,這樣即使在第三行變數a改變賦值,指向物件‘hello world!’,b的值也是不會改變的。
五 共享引用和在原處修改
a=[1,2,3]
b=a
a='hello world!'
同樣的,上邊對列表a做物件的直接改變,b所指的物件[1,2,3]並沒有發生改變,所以b的值是沒有發生改變的,但是程式碼如如下情況的話,結果則有所不同
a=[1,2,3]
b=a
a[0]='hello world!'
這裡並不是改變a,而是改變了a所指引的物件的第一個元素值,這樣就改變的原本的物件值,那麼原先所有指向該物件的變數的值都會跟著改變。 這樣就引出另外一個問題,假如要對某個變數做一份拷貝而且不隨原先的變數所指的物件的改變而發生改變時,該如何。其實就是新闢出另外一個記憶體空間來儲存拷貝的資料,有幾種方法:
a=[1,2,3]
b=a[:]
b=copy.copy(a)
b=copy.deepcopy(a)
三種方法的應用場合和結果根據物件型別有所不同。第一種採用切片的方法只適用於序列型別(包括列表、字串,元組等)。後兩種方法則適用於任何型別,在運用於字典或者集合(Sets)型別時,如果沒有巢狀(nesting)的存在,則兩種的結果是一致的,假如字典或集合中存在巢狀而且想要把巢狀中的資料也一併完整拷貝,則只能使用copy.deepcopy()。
六 共享引用和相等
a=[1,2,3]
b=a
b==a #true
b is a #true
‘==’是相等操作符,判斷兩個被引用的物件的值是否相等,而’is ’ 操作符則作物件同一性判斷,也就是說前者即使是不同物件,只要物件的值相等,則返回true的結果;而後者則是判斷變數是否指向同一物件,只有指向同一物件才返回true的結果。
更多的具體可以參照learning Python的第六章
Reference: