python繼承object
1. python對象
眾所周知,Python是一門面向對象的語言,在Python無論是數值、字元串、函數亦或是類型、類,都是對象。
對象是在 堆 上分配的結構,我們定義的所有變數、函數等,都存儲於堆內存,而變數名、函數名則是一個存儲於 棧 中、指向堆中具體結構的引用。
要想深入學習Python,首先需要知道Python對象的定義。
我們通常說的Python都是指CPython,底層由C語言實現,源碼地址: cpython [GitHub]
Python對象的定義位於 Include/object.h ,是一個名為 PyObject 的結構體:
Python中的所有對象都繼承自PyObejct,PyObject包含一個用於垃圾回收的雙向鏈表,一個引用計數變數 ob_refcnt 和 一個類型對象指針 ob_type
從PyObejct的注釋中,我們可以看到這樣一句:每個指向 可變大小Python對象 的指針也可以轉換為 PyVarObject* (可變大小的Python對象會在下文中解釋)。 PyVarObejct 就是在PyObject的基礎上多了一個 ob_size 欄位,用於存儲元素個數:
在PyObject結構中,還有一個類型對象指針 ob_type ,用於表示Python對象是什麼類型,定義Python對象類型的是一個 PyTypeObject 介面體
實際定義是位於 Include/cpython/object.h 的 _typeobject :
在這個類型對象中,不僅包含了對象的類型,還包含了如分配內存大小、對象標准操作等信息,主要分為:
以Python中的 int類型 為例,int類型對象的定義如下:
從PyObject的定義中我們知道,每個對象的 ob_type 都要指向一個具體的類型對象,比如一個數值型對象 100 ,它的ob_type會指向 int類型對象PyLong_Type 。
PyTypeObject結構體第一行是一個PyObject_VAR_HEAD宏,查看宏定義可知PyTypeObject是一個變長對象
也就是說,歸根結底 類型對象也是一個對象 ,也有ob_type屬性,那 PyLong_Type 的 ob_type 是什麼呢?
回到PyLong_Type的定義,第一行 PyVarObject_HEAD_INIT(&PyType_Type, 0) ,查看對應的宏定義
由以上關系可以知道, PyVarObject_HEAD_INIT(&PyType_Type, 0) = { { _PyObject_EXTRA_INIT 1, &PyType_Type } 0} ,將其代入 PyObject_VAR_HEAD ,得到一個變長對象:
這樣看就很明確了,PyLong_Type的類型就是PyType_Typ,同理可知, Python類型對象的類型就是PyType_Type ,而 PyType_Type對象的類型是它本身
從上述內容中,我們知道了對象和對象類型的定義,那麼根據定義,對象可以有以下兩種分類
Python對象定義有 PyObject 和 PyVarObject ,因此,根據對象大小是否可變的區別,Python對象可以劃分為 可變對象(變長對象) 和 不可變對象(定長對象)
原本的對象a大小並沒有改變,只是s引用的對象改變了。這里的對象a、對象b就是定長對象
可以看到,變數l仍然指向對象a,只是對象a的內容發生了改變,數據量變大了。這里的對象a就是變長對象
由於存在以上特性,所以使用這兩種對象還會帶來一種區別:
聲明 s2 = s ,修改s的值: s = 'new string' ,s2的值不會一起改變,因為只是s指向了一個新的對象,s2指向的舊對象的值並沒有發生改變
聲明 l2 = l ,修改l的值: l.append(6) ,此時l2的值會一起改變,因為l和l2指向的是同一個對象,而該對象的內容被l修改了
此外,對於 字元串 對象,Python還有一套內存復用機制,如果兩個字元串變數值相同,那它們將共用同一個對象:
對於 數值型 對象,Python會默認創建0~2 8 以內的整數對象,也就是 0 ~ 256 之間的數值對象是共用的:
按照Python數據類型,對象可分為以下幾類:
Python創建對象有兩種方式,泛型API和和類型相關的API
這類API通常以 PyObject_xxx 的形式命名,可以應用在任意Python對象上,如:
使用 PyObjecg_New 創建一個數值型對象:
這類API通常只能作用於一種類型的對象上,如:
使用 PyLong_FromLong 創建一個數值型對象:
在我們使用Python聲明變數的時候,並不需要為變數指派類型,在給變數賦值的時候,可以賦值任意類型數據,如:
從Python對象的定義我們已經可以知曉造成這個特點的原因了,Python創建對象時,會分配內存進行初始化,然後Python內部通過 PyObject* 變數來維護這個對象,所以在Python內部各函數直接傳遞的都是一種泛型指針 PyObject* ,這個指針所指向的對象類型是不固定的,只能通過所指對象的 ob_type 屬性動態進行判斷,而Python正是通過 ob_type 實現了多態機制
Python在管理維護對象時,通過引用計數來判斷內存中的對象是否需要被銷毀,Python中所有事物都是對象,所有對象都有引用計數 ob_refcnt 。
當一個對象的引用計數減少到0之後,Python將會釋放該對象所佔用的內存和系統資源。
但這並不意味著最終一定會釋放內存空間,因為頻繁申請釋放內存會大大降低Python的執行效率,因此Python中採用了內存對象池的技術,是的對象釋放的空間會還給內存池,而不是直接釋放,後續需要申請空間時,優先從內存對象池中獲取。
2. python的class中的object是什麼意思
object 是指這個類繼承的最頂級的對象。python3.x 中已經可以省略object,可直接
classSample():
pass
3. python中的instance是什麼對象類型
面向對象最重要的概念就是類(Class)和實例(Instance),必須牢記類是抽象的模板,比如Student類,而實例是根據類創建出來的一個個具體的「對象」,每個對象都擁有相同的方法,但各自的數據可能不同。
仍以Student類為例,在Python中,定義類是通過class關鍵字:
class Student(object):
pass
class後面緊接著是類名,即Student,類名通常是大寫開頭的單詞,緊接著是(object),表示該類是從哪個類繼承下來的,繼承的概念我們後面再講,通常,如果沒有合適的繼承類,就使用object類,這是所有類最終都會繼承的類。
定義好了Student類,就可以根據Student類創建出Student的實例,創建實例是通過類名+()實現的:
>>> bart = Student()
>>> bart
<__main__.Student object at 0x10a67a590>
>>> Student
<class '__main__.Student'>
可以看到,變數bart指向的就是一個Student的實例,後面的0x10a67a590是內存地址,每個object的地址都不一樣,而Student本身則是一個類。
可以自由地給一個實例變數綁定屬性,比如,給實例bart綁定一個name屬性:
>>> bart.name = 'Bart Simpson'
>>> bart.name
'Bart Simpson'
由於類可以起到模板的作用,因此,可以在創建實例的時候,把一些我們認為必須綁定的屬性強制填寫進去。通過定義一個特殊的__init__方法,在創建實例的時候,就把name,score等屬性綁上去:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
注意到__init__方法的第一個參數永遠是self,表示創建的實例本身,因此,在__init__方法內部,就可以把各種屬性綁定到self,因為self就指向創建的實例本身。
有了__init__方法,在創建實例的時候,就不能傳入空的參數了,必須傳入與__init__方法匹配的參數,但self不需要傳,Python解釋器自己會把實例變數傳進去:
>>> bart = Student('Bart Simpson', 59)
>>> bart.name
'Bart Simpson'
>>> bart.score
59
和普通的函數相比,在類中定義的函數只有一點不同,就是第一個參數永遠是實例變數self,並且,調用時,不用傳遞該參數。除此之外,類的方法和普通函數沒有什麼區別,所以,你仍然可以用默認參數、可變參數、關鍵字參數和命名關鍵字參數。
4. python 添加了這個奇怪的叫做 object 的 class,它究竟有什麼含義
在Python里,有一句話叫,一切皆對象。而對象的英文單詞就是object。
換句話這個object就代表了Python中的一切,開發Python的龜叔已經給object類定義常用的屬性和方法供認識使用。
當在Python2中,你定義類的時候,加上object,用內置函數dir(你定義類的名字)查看屬性和方法,你定義的類會默認繼承object這個基類(父類)的屬性和方法。如果不給object參數,dir時就只有你自己定義屬性和方法,沒有繼承object的。
你可以下去動手試試(我是手機端回答的問題,抱歉無法演示截圖)
然後,如果你使用的是Python3,當你定義類的時候,給了object參數就繼承。不給object參數也會默認繼承。不管你是
class A:
還是 class A():
都會自動的被Python識別為:
class A(object)(這也是Python3更人性化的一點)
5. Python 為什麼要繼承 object 類
沒有規定必須繼承OBJECT類。OBJECT類只是面向對象語言繼承精神的一種表現。例如OBJECTC,C++等語言在標准庫中都將所有類的基類定義位OBJECT,這樣的好處就是最大限度的利用代碼重用的的精神。但是不通語言中的OBJECT類的作用又很不一樣所以看看下面的介紹:回到PYTHON中為什麼要集成OBJECT:low-levelconstructorsnamed__new__()–低級別的構造函數.Note:Python的class__init__並不是其他語言意義上的構造函數,在new創建實例後對實例屬性初始化的函數.descriptors,–描述符.或者說描述符協議支持.descriptorprotocol__get__,__set__,__delete__等,可以閱讀descriptor文檔staticmethodsandclassmethods-靜態方法和類方法properties(computedattributes)–屬性訪問settergetter.decorators(introcedinPython2.4)–裝飾器.現在裝飾器語法糖遍布各Python框架.slots–用戶設置後可以限定實例的屬性.在Python2中替代__dict__,可以節省近2/3內存,Python3中可以不因為優化內存使用率而使用slots,因為__dict__結構內存做了優化,Note:__dict__並不是Python意義上的內置的dict,其實是一個proxy類.anewMethodResolutionOrder(MRO)–MRO方法解析次序改變(由左遞歸改為C3演算法)可能上面的你看著不太理解。通俗說一下py2.2後繼承object的目的是使這個類成為newstyleclass,沒有繼承object的為傳統classicclass,在本機進行了測試,環境為py2.7.3classFoo(object):passclassFoo1:passprinttype(Foo),type(Foo1)printdir(Foo)printdir(Foo1)printisinstance(Foo,object)printisinstance(Foo1,object)結果如下:['__class__','__delattr__','__dict__','__doc__','__format__','__getattribute__','__hash__','__init__','__mole__','__new__','__rece__','__rece_ex__','__repr__','__setattr__','__sizeof__','__str__','__subclasshook__','__weakref__']['__doc__','__mole__']TrueTrue(這個True有些疑問,Foo1不應是object的實例啊)
6. python 添加了這個奇怪的叫做 object 的 class,它究竟有什麼含義
在Python里,有一句話叫,一切皆對象。而對象的英文單詞就是object。
換句話這個object就代表了Python中的一切,開發Python的龜叔已經給object類定義常用的屬性和方法供認識使用。
當在Python2中,你定義類的時候,加上object,用內置函數dir(你定義類的名字)查看屬性和方法,你定義的類會默認繼承object這個基類(父類)的屬性和方法。如果不給object參數,dir時就只有你自己定義屬性和方法,沒有繼承object的。
你可以下去動手試試(我是手機端回答的問題,抱歉無法演示截圖)
然後,如果你使用的是Python3,當你定義類的時候,給了object參數就繼承。不給object參數也會默認繼承。不管你是
class
A:
還是
class
A():
都會自動的被Python識別為:
class
A(object)(這也是Python3更人性化的一點)
7. python中的object類有何作用
object是一個基類,或稱之為元類。
在python2.x上,不繼承object類的稱之為經典類,繼承了object類的稱之為新式類
關於它們的區別,你可以閱讀以下python2手冊中的這個部分:
https://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes
8. python中的instance是什麼對象類型
在python2中,如果定義類時繼承了object,那麼實例化後對象的type就是該類
>>>
class
Apple(object):
pass
...
>>>
red_apple
=
Apple()
>>>
type(red_apple)
<class
'__main__.Apple'>
>>>
但如果定義類的時候沒有繼承object,實例化後對象的type將會是
instance
>>>
class
Apple():
pass
...
>>>
green_apple
=
Apple()
>>>
type(Apple)
<type
'instance'>
>>>
去看urllib2的源代碼,你會發現build_opener返回的對象是從這個東西繼承而來的:
class
BaseHandler:
def
add_parent(self,
parent):
self.parent
=
parent
def
close(self):
self.parent
=
None
它沒有繼承object,所以,它的type是instance
繼承object的類的寫法叫做
New-style
classes,是在
python
2.2
中引入的,之前的寫法被稱作
Old
clasess或
Classic
classes