Python學習筆記總結(三)類

來源:互聯網
上載者:User

標籤:

一、類簡單介紹
1、介紹
類是Python物件導向程式設計(OOP)的主要工具,類建立使用class語句,通過class定義的對象。
類和模組的差異,類是語句,模組是檔案.
類和執行個體
執行個體:代表程式領域中具體的元素。
類是生產執行個體的工廠,執行個體就像帶有“資料"的記錄,而類是處理這些記錄的“程式”.
類是執行個體工程,類的屬性提供行為(資料以及函數[方法]),所有從類產生的執行個體都繼承該類的屬性。
類的一個執行個體可以通過:執行個體.屬性,執行個體.方法,獲得類的屬性和方法調用。類支援繼承,當我們對class語句產生的對象使用object.attribute這種方式時,這個運算式會在Python中啟動搜尋--搜尋對象串連樹,搜尋對象所屬的子類,然後搜尋到子類繼承的多個超類,直到尋找attribute首次出現的對象。
超類,子類。子類繼承超類,也能在樹中較低位置重新定義超類的變數名,從而覆蓋超類定義的行為(方法)
類方法調用,也就是附屬於類的函數屬性。
編寫類樹
以class語句和類調用來構造一些樹和對象。簡單概述:
*每個class語句會產生一個新的類對象
*每次類調用時,就會產生一個新的執行個體對象
*執行個體自動連接至建立了這些執行個體的類
*類串連至其超類的方式是:將超類列在類頭部的括弧內。其從左至右的順序會決定樹中的次序。
class     C2:
class    C3:
class    C1(C2,C3):
....
I1=C1()
I2=C2()
這裡例子是多重繼承,也就是說在類數中,類有一個以上的超類,在Python中,如果class語句中的小括弧
內有一個以上的超類(像這裡的C1),它們由左至右的次序會決定超類搜尋的順序。
附加在執行個體的屬性只屬於那些執行個體,但附加在類上的屬性則由所有子類及其執行個體共用。
*屬性通常是class語句中通過指派陳述式添加在類中,而不是嵌入在函數的def語句內。
*屬性通常是類中,對傳遞給函數的特殊參數(也就是self),做賦值運算而添加在執行個體中。【*】
類通過函數為執行個體提供行為,因為這類嵌套的def會在類中對變數名進行賦值,實際效果就是把屬性添加在
類對象之中了,從而可以由所有執行個體和子類繼承。
>>> class T:
...     def setname(self,who):
...             self.name=who
...
>>> I1=T()
>>> I1.setname(‘diege‘)
>>> print I1.name
diege
第一個特殊參數:self。
這個參數提供了被處理的執行個體的參照值。
因為類是多個執行個體的工廠,每當需要取出或設定正由某個方法調用所處理的特定的執行個體的屬性時,那些方法通常都會自動傳入參數self.
當方法對self屬性進行賦值時,會建立或修改類樹底端執行個體內的屬性,因為self自動引用正在處理的執行個體。self相當於執行個體本身。
__init__ 構造器方法
上面的例子中,在setname方法調用前,T類都不會把name屬性附加在執行個體之上。事實上,調用I1.setname前引用I1.name
會產生未定義變數名錯誤。如果類想確保name這樣的變數名一定會在其執行個體中設定,通常都會在構造時填好這個屬性。
>>> class T:       
...     def __init__(self,who):
...             self.name=who
>>> I1=T(‘diege‘)  
>>> print I1.name
diege
寫好並繼承後,每次從類產生執行個體時,Python都會自動地調用名為__init__的方法。新執行個體會如往常那樣傳入__init__的self參數,
而列在小括弧內任何值會成為第二以及其後的參數。其效果就是在建立執行個體時初始化了這個執行個體,而不要額外的方法調用。
這樣就不用在取得執行個體屬性前,調用一個其他方法實現,__init__相當初始化,預設之意。
__init__構造器方法,除了明確傳入類的名字的任何參數外,還隱性的傳入新執行個體。T(‘diege‘) ,隱性傳入了self(self代表新執行個體)
T(‘diege‘)建立了一個新的對象(執行個體對象),I1指派陳述式引用這個對象,通過I1.name就取得這個對象的name屬性。
OOP為了代碼重用
OOP就是代碼重用:分解代碼,最小化代碼的冗餘以及對現在的代碼進行定製來編寫程式,而不是實地修改代碼或從頭開始。
2、類代碼編寫基礎
類支援多個對象的產生,命名空間的繼承,運算子多載
1)、類產生多個執行個體對象
Python OOP模型中的兩種對象:類對象和執行個體對象。
類對象提供預設的行為,是執行個體對象的工廠。執行個體對象是程式處理的實際對象:各自都有獨立的命名空間。類對象來至於語句,而執行個體來至於調用。每次調用一個類,就會得到這個類的新執行個體。
a、類對象提供預設行為
b、執行個體對象是具體的元素
2)、類通過繼承進行定製
a、類通過繼承進行定製
b、類是模組內部的屬性
3)、類可以截獲Python運算子

二、class語句
一般形式
class    <name>(superclass,...):
    data=value
    def mothod(self,...):
        self.member=value
在class語句內,任何指派陳述式都會產生類屬性。
類幾乎就是命名空間,也就是定義變數名(屬性)的工具,把資料和邏輯匯出給用戶端。
怎麼樣從class語句得到命名空間的呢?過程如下。
就像模組檔案,位於class語句主體中的語句會建立起屬性。當python執行class語句時(不是調用類)
會從頭到尾執行其主體內的所有語句。在這個過程中,進行賦值運算會在這個類的範圍中建立變數名,從而成為對應
類對象中的屬性。因為,類就像模組和函數:
*就像函數一樣。class語句是範圍,由內嵌的指派陳述式建立變數名,就存在這個本地範圍內。
*就像模組內的變數名,在class語句內賦值的變數名會變成類對象中的屬性。
class是複合陳述式,任何種類的語句都可以位於其主體內:print ,=,if,def等。當class語句自身運行時,class語句內的所有
語句都會執行。在class語句內賦值的變數名會建立類屬性,而內嵌的def語句則會建立類方法,其他的指派陳述式也可以製作屬性。
class頂層的指派陳述式定義的屬性可以用於管理貫穿所有執行個體的資訊。
三、方法
方法調用需要通過執行個體,一般是通過執行個體調用的
instance.method(arg...)
這會自動翻譯成以下形式的類方法函數調用:
class.method(instance,args...)
class通過Python繼承搜尋流程找出方法名稱所在之處.
類方法的第一個參數通常稱為self。這個參數提供方法一個鉤子,從而返回調用的主體,也就是執行個體對象:
第一個參數self需明確
這個變數名的存在,會讓你明確指令碼中使用的是執行個體屬性名稱,而不是本地範圍或全域範圍中的變數名
1、調用超類的構造器
像其他屬性一樣___init__方法是由繼承進行尋找。也就是說,在構造時,Python會找出並且只調用一個__init__(樹中最低的那個)。如果要保證子類的構造方法也執行超類構造器的邏輯(啟用超類的構建代碼),一般都必須通過子類手動明確地調用超類的__init__方法(通過超類名稱名稱來調用,手動傳入到self執行個體:Superclass.__init__(self,...) )。
class Super:
    def __init__(self,x):
        ...default code...
class Sub(Super):
    def __init__(self,x,y):
        Super.__init__(self,x)  ###還是有用到的地方。
        ...custom code...
如果真的想運行超類的構造方法並做適當的修改,自然只能用這種方法進行調用:沒有這樣的調用,子類會完全取代(覆蓋)超類的構造器,或者子類沒有設定__init__構造器的情況下完全繼承超類的構造器方法(__init__方法也會繼承)。
2、其他方法調用的可能。
這種通過類調用方法的模式(類中調用類的方法(不一定自己)),是擴充繼承方法行為(而不是完全取代).
3、繼承
像class語句這樣的命名空間工具的重點就是支援變數名繼承。這裡擴充關於屬性繼承的一些機制和角色。在Python中,當對對象進行點號運算時,就會發生繼承,而且涉及到搜尋屬性定義樹(一或多個命名空間)。每次使用obecj.attr形式的運算式時(objecj是執行個體或類對象),Python會從頭到尾搜尋命名空間樹,先從對象開始,找到第一個attr為止。這包括在方法中對self屬性的引用。因為樹中較低的定義會覆蓋較高的定義,繼承構成了專有化的基礎。
4、屬性樹的構造
命名空間樹構造以及填入變數名的方式,通常來說:
【*】執行個體屬性是由對方法內self屬性進行賦值運算而產生的
【*】類屬性是通過class語句內頂層的語句(指派陳述式)而產生的
【*】超類連結通過class語句首行的括弧內列出類而產生的
5、繼承方法的專有化- 重載-回調
繼承樹搜尋模式,變成了將系統專有化的最好方式。因為繼承會先在子類尋找變數名,然後才尋找超類,子類就可以對超類的屬性重新定義來取代預設的行為。把系統做成類的層次,再新增外部的子類來對其進行擴充,而不是在原處修改已存在的邏輯。
重新定義繼承變數名的概念引出了各種專有化技術。
當子類重新定義一個方法時又調用了超類同樣的方法來實現這個子類方法的部分功能,這裡就用到回調技術。
這樣實現了預設的行為,換句話說,Sub.mothod只是擴充了Super.mothod的行為,而不是完全取代他。
6、抽象類別
抽象類別就是會調用方法的類,但沒有繼承或定義該方法,而是期待該方法由子類填補。當行為無法預測,非得等到更為具體的子類編寫時才知道,可用這種方式把類通用化。這種“填空”的代碼結構一般就是OOP軟體的架構。從delegate方法的角度來看,這個例子中的超類有時也稱作是抽象類別--也就是類的部分行為預設是由其子類所提供的。如果預期的方法沒有在子類定義,當繼承搜尋失敗時,Python會引發為定義,變數名的異常。類的編寫者偶爾會使用assert語句,使這種子類需求更為明顯,或者引發內建的異常NotImplementedError
class Super:
        def method(self):
                print "in Super.method"
        def delegate(self):
                self.action()
class Provider(Super):
        def action(self):
                print "in Provider.method"
類有特殊的屬性__name__類的名字,就像模組一樣有__name__屬性模組的名字。類中預設為類行首行中的類名稱的字串。
四、運算子多載
重載的關鍵概念
*運算子多載讓類攔截常規的Python運算。
*類可重載所有Python運算式運算。
*類可重載列印,函數調用,屬性點號運算等運算。
*重載使類執行個體的行為像內建類型。
*重載是通過提供特殊名稱的類方法來實現的。
如果類中提供了某些特殊名稱的方法,當類執行個體出現在運算有關的運算式的時候,Python就會自動調用這些方法。
1、 常見的運算子多載方法
方法        重載        調用
__init__    構造器方法    對象建立:X=Class()
__del__        析構方法    對象收回
__add__        運算子+        X+Y,X+=Y
__sub__        運算子-        X-Y,X-=Y
__or__        運算子|(位OR)    X|Y X|=Y
__repr__,__str__ 列印,轉換    print X【__str__】、repr(X)、str(X)
__call__    函數調用    X()
__getattr__    點號運算    X.undefined
__setattr__    屬性指派陳述式    X.any=Value
__getitem__    索引運算    X[key],沒有__iter__時的for迴圈和其他迭代器
__setitem__    索引指派陳述式    X[key]=value
__len__        長度            len(X),真值測試
__cmp__        比較            X==Y,X
__lt__        特定的比較        X<Y(or else __cmp__)
__eq__        特定的比較        X==Y(or else __cmp__)
__radd__    左側加法 +        Noninstance + X
__iadd__    實地(增強)的加法    X+=Y(or else __add__)
__iter__    迭代環境        用於迴圈,測試,列表,映射及其他
所有重載方法的名稱前後都有兩個底線,以便把同類中定義的變數名區別開來。特殊方法名稱和運算式或運算的映射關係,是由Python語言預先定義好的。
所有運算子多載的方法都是選用的:如果沒有寫某個方法,那麼定義的類就不支援該運算。多數重載方法只用在需要對象行為表現得就像內建函數一樣的進階程式中。然而,__init__構造方法常出現在絕大多數類中。
__getitem__攔截索引運算
__getitem__方法攔截執行個體的索引運算。當執行個體X出現X[i]這樣的索引運算中時,Python會調用這個執行個體繼承的__getitem__方法。
(如果有),把X作為第一個參數傳遞,並且放括弧內的索引值傳遞給第二個參數
2、__iter__和_getitem__實現迭代
for迴圈的作用是從0到更大的索引值,重複對序列進行索引運算,直到檢測到超出邊界的異常。
__getitem__也可以是Python中一種重載迭代的方式,如果定義了這個方法,for迴圈每次迴圈時都會調用類的__getitem__
任何支援for迴圈的類也會自動支援Python所有迭代環境,包括成員關係測試in,列表解析,內建函數map,列表和元組賦值運算以及類型構造方法也會自動調用__getitem__(如果定義的話)。如今,Python中所有的迭代環境都會先嘗試__iter__方法,再嘗試__getitem__。如果對象不支援迭代協議,就會嘗試索引運算。
從技術角度來將,迭代環境是通過調用內建函數iter去嘗試尋找__iter__方法來實現的,而這種方法應該返回一個迭代器對象。
如果已經提供了,Python就會重複調用這個迭代器對象的next方法,直到發生StopIteration異常。如果沒有找到__iter__方法
,Python會改用__getitem__機制,就像之前那樣通過位移量重複索引,直到引發IndexError異常。
迭代器對象就是執行個體self,因為next方法是這個類的一部分。在較為複雜的的情境中,迭代器對象可定義為個別的類或對象,有自己的狀態資訊,對相同資料支援多種迭代。以Python的raise語句發出訊號表示迭代結束。__iter__對象會在調用過程中明確地保留狀態資訊。所以比__getitem__具體更好的通用性。__iter__迭代器比__getitem__更複雜和難用。迭代器是用來迭代,不是隨機的索引運算。事實上,迭代器根本沒有重載索引運算式.
__iter__機制是在__getitem__中所見到的其他所有迭代環境的實現方式(成員關係測試,類型構造器,序列賦值運算)。和__getitem__不同的是,__iter__只迴圈一次,而不是迴圈多次,迴圈之後就變為空白,每次新的迴圈,都得建立一個新的迭代器對象。
3、其他常用運算子多載
__del__是析構器
每當執行個體產生時,就會調用__init__構造方法,每當執行個體空間被收回執行__del__方法
__setattr__會攔截所有指派陳述式,一般不用。
__repr__,__str__ 列印,轉換    print X、repr(X)、str(X)
__call__攔截調用:如果定義了,Python就會為執行個體應用函數調用運算式運行__call__方法。
當需要為函數的API編寫介面時,__call__就變得很用有:這可以編寫遵循所需要的函數來調用介面對象。
四、命名空間:完整的內容
點號和無點號的變數,會用不同的方式處理,而有些範圍是用於對對象命名空間做初始設定的。
*無點號運算的變數名(例如,X)與範圍相對應
*點號的屬性名稱(如object.X)使用的是對象的命名空間。
*有些範圍會對對象的命名空間進行初始化(模組和類)
1、簡單變數名:如果賦值就不是全域變數
無點號的簡單運算名遵循函數LEGB範圍法則:
指派陳述式(X=value)
    使變數名為本地變數:在當前範圍內,建立或改變變數名X,除非聲明它是全域變數。如在函數的內的指派陳述式。
引用(X)
    在當前範圍內搜尋變數名X,之後是在任何以及所有的嵌套函數中,然後是在當前的全域範圍中搜尋,最後在內建範圍中搜尋。
2、屬性名稱:對象命名空間
點號的屬性名稱指的是特定對象的屬性,並且遵守模組和類的規則。就類和執行個體對象而言,引用規則增加了繼承搜尋這個流程。
指派陳述式(object.X=value)
    在進行點號運算的對象的命名空間內建立或修改屬性名稱X,並沒有其他作用。繼承樹的搜尋只發生在屬性引用時,而不是屬性的賦值運算時
引用(object.X)
    就基於類的對象而言,會在對象內搜尋屬性名稱X,然後是其上所有可讀取的類(使用繼承搜尋流程).對於不是基於類的對象而言,例如模組,則是從對象中直接讀取X(可能是的屬性包括,變數名,函數,類)。
3、命名空間:賦值的位置將變數名分類
在Python中,賦值變數名的場所相當重要:這完全決定了變數名所在範圍或對象。一下執行個體總結了命名空間的概念。
# vim manynames.py
X=11    #模組屬性 全域
def f():
        print X  #函數(本地)範圍內沒有X,嵌套函數沒有X變數,當前全域範圍(模組的命名空間內)有,顯示全域
def g():
        X=22  #定義本地範圍變數X
        print X #搜尋函數(本地)範圍內變數X,有列印
class C:
        X=33     #定義的類屬性,類的命名空間
        def m(self):
                X=44    #貌似在這裡沒有什麼意義
                self.X=55 #定義類執行個體的屬性,執行個體的命名空間
if __name__==‘__main__‘:
        print X    #列印模組屬性 結果11
        f()    #調用f(),f()返回模組全域變數的X 11
        g()    #調用g(),g()返回函數內局部變數X 22
        print X #列印 模組全域變數的裡變數,模組的屬性 11

        obj=C()    #調用類的方法產生執行個體
        print obj.X #列印執行個體的屬性X X繼承類的屬性,所以為33

        obj.m() #執行個體調用類的m方法,
        print obj.X #顯示這個X屬性 因為上一步m方法設定了執行個體的屬性X,為55
# python manynames.py
11
11
22
11
33
55
範圍總是由原始碼中指派陳述式的位置來決定,而且絕不會受到其匯入關係的影響。屬性就像是變數,在賦值之後才會存在。
而不是在賦值前。通常情況下,建立執行個體屬性的方法是在類的__init__構造器方法內賦值。
通常說來,在指令碼內不應該讓每個變數使用相同的命變數名。
4、命名空間字典
模組的命名空間實際上是以字典的形式實現的,並且可以由內建屬性__dict__顯示這一點。類和執行個體對象也是如此:屬性點號運算
其內部就是字典的索引運算,而屬性繼承其實就是搜尋連結的字典而已。實際上,執行個體和類對象就是Python中帶有連結的字典而已,
>>> class Super():
...     def hello(self):
...             self.data1=‘diege‘
...
>>> class Sub(Super):
...     def hola(self):
...             self.data2=‘eggs‘
...
製作子類的執行個體時,該執行個體一開始會是空的命名空間字典,但是有連結會指向它的類,讓繼承搜尋能順著尋找。
實際上,繼承樹可在特殊的屬性中看到,你可以進行查看。執行個體中有個__class__屬性連結到了它的類,而類有個__base__屬性。
就是元組,其中包含了通往更高的超類的串連。
>>> X=Sub()                    
>>> X.__dict__
{}
>>> X.__class__
<class __main__.Sub at 0x2850353c>
>>> Y=Super()
>>> Y.__dict__
{}
>>> Y.__class__
<class __main__.Super at 0x285034ac>
>>> Sub.__bases__
(<class __main__.Super at 0x285034ac>,)
>>> Super.__bases__  
()
當類為self屬性賦值時,會填入執行個體對象。也就是說,屬性最後會位於執行個體的屬性命名空間字典內,而不是類的。
執行個體對象的命名空間儲存了資料,會隨執行個體的不同而不同,而self正是進入其命名空間的鉤子。
>>> Y=Sub()
>>> X.hello()
>>> X.__dict__
{‘data1‘: ‘diege‘}
>>> X.hola()  
>>> X.__dict__
{‘data1‘: ‘diege‘, ‘data2‘: ‘eggs‘}
>>> Sub.__dict__
{‘__module__‘: ‘__main__‘, ‘__doc__‘: None, ‘hola‘: <function hola at 0x284954c4>}
>>> Super.__dict__
{‘__module__‘: ‘__main__‘, ‘hello‘: <function hello at 0x28495f0c>, ‘__doc__‘: None}
>>> Sub.__dict__.keys(),Super.__dict__.keys()
([‘__module__‘, ‘__doc__‘, ‘hola‘], [‘__module__‘, ‘hello‘, ‘__doc__‘])
>>> Y.__dict__
{}
Y是這個類的第2個執行個體。即時X的字典已由方法內的指派陳述式做了填充,Y還是空的命名空間字典。每個執行個體都有獨立的命名空間字典,一開始是空的,可以記錄和相同類的其他執行個體命名空間字典中屬性,完全不同的屬性。
因為屬性實際上是python的字典鍵,其實有兩種方式可以讀取並對其進行賦值:通過點號運算,或通過鍵索引運算。
>>> X.data1,X.__dict__[‘data1‘]
(‘diege‘, ‘diege‘)
>>> X.data3=‘lily‘
>>> X.__dict__               
{‘data1‘: ‘diege‘, ‘data3‘: ‘lily‘, ‘data2‘: ‘eggs‘}
>>> dir(X)
[‘__doc__‘, ‘__module__‘, ‘data1‘, ‘data2‘, ‘data3‘, ‘hello‘, ‘hola‘]
>>> dir(Sub)
[‘__doc__‘, ‘__module__‘, ‘hello‘, ‘hola‘]
>>> dir(Super)
[‘__doc__‘, ‘__module__‘, ‘hello‘]
對執行個體賦值,隻影響執行個體,不會影響執行個體的類和超類
5、命名空間串連
__class__和__bases__這些屬性可以在程式碼內查看繼承層次。可以用他來顯示類樹

五、類設計
1、Python和OOP
Python和OOP實現可以概括為三個概念。
繼承
    繼承是基於Python中屬性尋找(在X.name運算式中)
多態
    在X.method方法中,method的意義取決於X的類型(類)
封裝
    方法和運算子實現行為,資料隱藏預設是一種慣例
類和繼承:是“一個”關係 (is a)
從程式員的角度來看,繼承是由屬性點號運算啟動的,由此觸發執行個體,類以及任何超類中變數名搜尋。
從設計師的角度看,繼承是一種定義集合成員關係的方式:類定義了一組內容屬性,可由更具體的集合(子類)繼承和定製。
子類和超類的繼承是1對1的關係
類和組合:”有一個“關係 (has a)
從程式員的角度來看,組合設計到把其他對象嵌入到容器物件內,並使其實現容器方法。
對設計師來說,組合是另一種表示問題領域中的關係的方法。
但是組合不是集合的成員關係,而是組件,也是整體的組成部分。
組合也反映了個組成部分之間的關係,通常稱為“有一個”(has a)關係。Python中,“組合”(彙總)就是指內嵌對象集合體。
類和持久性
持久性:保證資料的持久性,將資料儲存在檔案或者資料庫,繼續儲存。
pickle和shelve模組和類執行個體結合起來使用效果很好,通過單個步驟儲存到硬碟上。
pickle機制把記憶體中的對象轉換成序列化的位元組流,可以儲存在檔案中。
Shelve會自動把對象pickle產生按鍵讀取的資料庫,而此資料庫匯出類似於字典的介面.
pickle
>>> pickle.dump(obj.server,file) #寫入
>>> objread=pickle.load(file)  #讀取
shelve
>>> dbase=shelve.open(‘datafile‘)
>>> dbase[‘key‘]=obj.server 寫入
>>> shtest=shelve.open(‘datafile‘)
>>> shtest[‘name‘]      #讀取\
2、OOP和委託
所謂的委託,通常就是指控制器對象內嵌其他對象,而把運算請求傳給那些對象。控制器負責管理工作。
在Python中,委託通常是以__getattr__鉤子方法實現的,因為這個方法會攔截對不存在屬性的讀取,封裝類(代理類)可以使用__getattr__把任意讀取轉寄給封裝的對象。封裝類包有被包括對象的介面。而且自己也可以增加其他運算。
class wrapper:
    def __init__(self,object):
        self.wrapped=object
    def __getattr__(self,attrname):        #__getattr__點號運算,這裡重載內建getattr方法列印傳入類執行的方法,並把屬性請求傳入給對象,使用對象預設的方法。委託
        print ‘Trace:‘,attrname
        return getattr(self.wrapped,attrname)
3、多重繼承
在class語句中,首行括弧內可以列出一個以上的超類。當這麼做時,就在使用所謂的多重繼承:類和其執行個體繼承了列出的所有超類的變數。搜尋屬性時,Python會由左到右搜尋類首行中的超類,直到找到相符者。
通常意義上講,多重繼承是類比屬於一個集合以上的對象的好辦法,例如一個人可以是工程師,作家,音樂家。因為,可以繼承這些集合的特性。
多重繼承最常見的使用者是作為“混合”超類的通用方法。這類超類一般都稱呼混合類:他們提供方法,可以通過繼承將其加入應用類。
每個執行個體都有內建的__class__屬性,引用了它所繼承的類,而每個類都有__name__屬性,用用了首行中的變數名,所以self.__class__.__name__是取出執行個體的類的名稱
>>> x.__class__.__module__     
‘trac‘
>>> x.__module__        
‘trac
而是用self.__module__或 self.__class__.__module__則取出執行個體引用模組的名稱
4、類是對象:通用對象的工廠
類是對象,因此它很容易在程式中進行傳遞,儲存在資料庫結構中。也可以把類傳給產生任意種類對象的函數。這類函數在OOP設計領域偶爾稱為工廠。
工廠式的函數或程式碼,在一些情況下很方便,因為他們可以讓我們取出並傳入沒有預先在程式碼中硬式編碼類。實際上,這些類在編寫程式時可能還不存在。抽象類別。
>>> def factory(aClass,*args):
...     return apply(aClass,args)
...
這裡定義了一個對象產生器函數,稱為factory.它預期傳入的是類對象(任何對象都行),還有該類構造器的一個或多個參數。這個函數使用apply調用該函數並返回執行個體。
5、方法是對象:綁定或無綁定
方法也是一種對象,很像函數。類方法能有執行個體或類來讀取。實際上Python中就有兩種方式。
無綁定類方法對象:無self
    通過對類進行點號運算從而擷取類的函數屬性,會傳回無綁定(unboud)方法對象。調用該方法時,【必須明確提供執行個體對象】作為第一個參數。
綁定執行個體方法對象:
    self+函數對通過對執行個體進行全運算從而擷取類的函數屬性,會傳回綁定(bound)方法對象。Python在Binder 方法對象中自動把執行個體和函數打
包,所以,不用傳遞執行個體去調用該方法。執行個體已擁有該方法。
這兩種方法都是功能齊全的對象,可四處傳遞,保持在列表內等。執行時兩者都需要第一參數的執行個體(也就是self的值).
6、類和模組
都是命名空間
模組
        * 是資料/邏輯套件
        * 由Python檔案或C擴充編寫成
        * 通過匯入使用

        *實現新的對象
        *由class語句建立
        *通過調用使用
        *總是存在於模組中。
類支援其他模組不支援的功能。例如,運算子多載,產生多個執行個體以及繼承。

 

Python學習筆記總結(三)類

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.