徹底理解Python中對象、對象與變量引用的關系
一、對象(Object)
在Python里,一切皆對象,完全的面向對象。
Python中,所有的元素都是對象。
(對象是一個抽象,可想象成現(xiàn)實中的一個實際物體。)
1.對象定義:
對象是分配的一塊內存,有足夠的空間去表示它們所代表的值?!?《Learning Python》
或者:一塊內存空間,擁有特定的值,支持特定類型的相關操作。
2.對象的特點:
Python中,對象具有三要素:標識(identity)、類型(type)、值(value)。

標識(identity):
用于唯一標識對象,通常對應對象在計算機內存中的地址。
使用內置函數(shù)?id(obj)?返回對象唯一標識。
類型(type):
對象中含有標準的頭部信息HEAD:類型標識符。
標識對象類型,表示對象存儲的數(shù)據(jù)的類型。
類型可以限制對象的取值范圍和可執(zhí)行的操作。
使用內置函數(shù)?type(obj)?返回對象所屬類型。
每一個對象都有兩個標準的頭部信息:
1.類型標識符,去標識對象的(數(shù)據(jù))類型;
2.引用計數(shù)器,記錄當前對象的引用的數(shù)目。
(回收機制:變量的引用計數(shù)器為0,自動清理。 ※ 較小整數(shù)型對象有緩存機制。)
值(value):
表示對象存儲的數(shù)據(jù)的信息。
使用內置函數(shù)print(obj)可以直接打印值。
再看一遍圖

操作符?is
?和?==?
的區(qū)別與關系:
is
判斷兩個變量是否指向同一個對象,比較兩個引用是否代表了內存中同一個地址,是否指向同一塊內存空間。
通過?id(obj)?返回值判斷。
==
比較對象的本身內容{類型(type)和值(value)}是否一致。
默認會調用對象的__eq__方法。
關系:
當id相同時,is 為True,兩者的type和value肯定相同,
但當type與value相同時,== 為True,但兩者的id不一定相同。
例如:
列表
整數(shù)
小整數(shù) small_ints 和 短字符串緩存池
CPython出于性能優(yōu)化的考慮,把頻繁使用的整數(shù)對象用一個small_ints的對象池緩存起來。
small_ints緩存的整數(shù)值被設定為[-5, 256]這個區(qū)間。
如果使用CPython解釋器,在任何引用這些整數(shù)的地方,都不需要重新創(chuàng)建int對象,而是直接引用緩存池中的對象。
如果整數(shù)不在該范圍內,那么即便兩個整數(shù)的值相同,它們也是不同的對象。
例如:
小整數(shù)
短字符串
3.對象的存儲和創(chuàng)建:
Python中,對象存儲在堆(heap)內存中。
對象通過調用__new__創(chuàng)建。
二、變量(Variable):
變量是一個系統(tǒng)表的元素,擁有指向對象的連接的空間?!禠earning Python》
Python中,
變量用來指向任意的對象,是對象的引用。
Python變量更像是指針,而不是數(shù)據(jù)存儲區(qū)域。
變量,可看作對象的一個臨時「標簽」,是引用,
而非裝有對象的容器。
例如:
房間門外掛著“張先生的房間”的門牌,
礦泉水瓶身上貼的一張寫著“劉女士的礦泉水”的標簽。
給一個變量賦值(Assignment),
等于把這個標簽貼到一個對象上,
重新賦值,是撕下標簽貼到另一個對象上。

上圖給2個變量賦給一樣的值,就相當于把2個標簽貼在同一個對象上,
代碼如下:
三、引用關系:
引用是自動形成的從變量到對象的指針。——《Learning Python》
在Python中,賦值(=)操作時,從變量到對象自動建立的連接關系,稱為引用。
引用是一種關系,以內存中的指針的形式實現(xiàn)。
1.賦值操作:
是對象標識(identity)的傳遞,片面的理解是內存地址的傳遞。
變量一旦使用完畢,可被清理(撕掉標簽)。
2.賦值語句:
Python賦值語句中,
當把一個對象(object)賦給一個數(shù)據(jù)結構元素或者變量名時,
Python總是會存儲對象的引用,而不是對象的一個拷貝。
賦值操作符?=
定義變量的'=' 與數(shù)學中的'=' 意義不同。
Python 中的賦值符號'='的左邊是變量名,右邊是對象值Value,表示將右邊的值傳遞給左邊。
所以 '=' 是右連接性,對象值的傳遞順序是從右到左。
Python中'=='是比較符號,代表左右值相等。
3.引用方式:
3.1簡單引用:
一個對象 3 (int整數(shù)型,不可變對象),用變量名 a 表示:
Python中,從概念上,
a = 3 反映所有賦值語句執(zhí)行的三個步驟:
1.創(chuàng)建一個對象來代表值 3 。
2.創(chuàng)建一個變量 a ,如果它還沒有創(chuàng)建的話。
3.將變量 a 與 新的對象 3 相連接。

※ 需要明確 a 不是對象本身, a 只是對象 3 的引用。
3.2共享引用

a 指向對象3,
b = a 賦值引用,于是 b 也指向3。
a 和 b 都共同引用了同一個對象 3。
然后,
a 重新指向一個新對象'spam'(字符串,不可變對象),b 依然指向對象 3。

列表的共享引用
總結:
對象是分配的一塊內存,有足夠的空間去表示它們所代表的值。
變量是一個系統(tǒng)表的元素,擁有指向對象的連接的空間。
引用是自動形成的從變量到對象的指針。
補充:
Python 動態(tài)類型語言
變量不需要顯示聲明類型。對象的類型是內置的。
根據(jù)變量引用的對象,Python解釋器自動跟蹤對象的類型,從而確定類型,所以是動態(tài)型。
Python 強類型語言
每個對象都有數(shù)據(jù)類型,且只支持該類型支持的操作。
標識符:用于變量、函數(shù)、模塊等的名稱。
標識符命名規(guī)則:
1.區(qū)分大小寫:如abc 和 ABC是不同的。
2.第一個字符必須是字母、下劃線,其后的字符是:字母、數(shù)字、下劃線。
3.不能使用關鍵字。如:if 、or、while等
4.雙下線開頭的和結尾的名稱通常有特殊含義,盡量避免這種寫法。如__init__是構造函數(shù)。
