變量只是在一個特定的時間點對某一特定類型對象的引用,當變量出如今表達式中時,它會立刻被當前引用的對象所代替,也就是說,在一個程序,同一個變量名能夠引用任何類型的對象。而不受限於它最初的引用。類型屬於對象,而不是屬於變量,給一個變量賦一個新值,並非替換了原始的對象,而是讓這個變量去引用徹底不一樣的一個對象。python
>>> a=11web
>>> type(a)緩存
<class 'int'>優化
>>> a='abc'spa
>>> type(a)指針
<class 'str'>orm
>>>對象
變量和對象保存在內存中的不一樣部分,經過鏈接(賦值=等)相關聯,在內部,變量事實上是到對象內存空間的一個指針,它們這具鏈接關係也稱爲「引用」內存
而對於對象,在系統內部會分配一塊內存,有足夠的空間去表示它們所表明的值,每一個對象都有兩個標準的頭部信息:一個類型標誌符,一個引用計數器,後者用來決定是否是能夠回收這個對象字符串
對象的垃圾收集
每當給一個變量名賦予了一個新的對象,以前的那個對象佔用的空間就會被回收(若是它沒有被其它的變量名或對象所引用的話),原對象的空間自動被放入自由內存空間池,等待後來的對象使用
共享引用
多個變量名引用了同一個對象,以下面的例子,變量 a和b都是引用常量表達式建立的對象3,而再次給變量a賦值時,b引用的值沒有跟着改變
>>> a=3
>>> b=a
>>> type(b)
<class 'int'>
>>> a=4
>>> b
3
共享引用和在原處修改
有一點要注意的,由於list是容許在原處修改的,所以,若是兩個變量引用的是同一個列表對象,那麼,經過其中一個變量去修改列表,都會影響到另外一個變量的引用值
>>> l1 = [1,b,3]
>>> l2= l1
>>> l1[1]='c'
>>> l2
[1, 'c', 3]
若是要避免這個狀況發現,須要使用拷貝對象,對於列表,可使用標準庫的copy模塊,也可使用從頭至尾的分片,這樣,兩個變量就指向了不一樣的內存區域了
>>> L1=[1,2,4]
>>> L2=L1[:]
>>> L1[0]=2
>>> L1
[2, 2, 4]
>>> L2
[1, 2, 4]
>>>
而對於字典和集合,應該使用X.copy()的方式調用,能夠直接在原處改變的對象有列表、字典、以及一些經過class定義的對象
>>> import copy
>>> L3=copy.copy(L1)
>>> L3
[2, 2, 4]
>>>
共享引用和相等
對斷定兩個變量是否是相等,可使用「==」和「is」,但兩都有不一樣的意思,「==」是指變量所引用的對象值相等,而「is」 則是指兩個變量引用的是同一個對象,is只是比較實現引用的指針
>>> L=[1,2,3]
>>> M=[1,2,3]
>>> L==M
True
>>> L is M
False
>>>
但python爲了優化執行速度,對於不可變的對象,如數字、字符串對像,會有一種緩存機制,同一值的對象只生成一個對象內存空間,也就是說,對變量所引用的對象(僅限數字、字符串、元組這類不可變的對象)值相等時,這個對象是同一個對象,能夠通sys 模塊裏的getrefcount()可查看某個對象被引用的次數
>>> a=5
>>> b=5
>>> a == b
True
>>> a is b
True
>>> str1= "hello"
>>> str2= "hello"
>>> str1 == str2
True
>>> str1 is str2
True
>>>
>>> import sys
>>> sys.getrefcount("hello")
4
>>> str3="hello"
>>> sys.getrefcount("hello")
5
>>>