一,面向對象基礎1
c#、Java:只能用面向對象編程
Ruby、python、php:函數編程 + 面向對象php
1.面向過程編程2
就是程序最底層的實現過程
2.函數式編程3
就是將最底層的實現過程封裝到函數裏,調用函數的方法編程
3面向對象編程4
就是將若干函數封裝到一個類裏,調用類來實現裏面的函數方法python
注意:面向對象不是全部狀況都適用 5編程
面向對象編程6
須要定義一個類 ,將功能函數寫在類裏,這樣類裏面的函數就叫作,實現一個類功能的方法,要使用這個類的方法時,建立這個類的對象賦值給一個變量,經過對象變量找到這個類下面的功能函數來實現(功能)的方法c#
#!/usr/bin/env python # -*- coding:utf-8 -*- class fgjk: #定義一個類,在類裏寫函數來實現類的方法 def f1(self,a): #方法1 return a + 1 def f2(self,b): #方法2 pass def f3(self,c): #方法3 pass a1 = fgjk() #建立類對象賦值給一個變量 a2 = a1.f1(3) #調用類下面的一個函數傳入參數,來實現一個功能,叫作方法 print(a2) #打印出這個方法的結果 #輸出fgjk類下面的f1()方法 # 4
class關鍵字,定義一個類7函數式編程
功能:定義一個類函數
使用方法:class 類名稱:spa
格式:class fgjk:3d
#!/usr/bin/env python # -*- coding:utf-8 -*- class fgjk: #定義一個類,在類裏寫函數來實現類的方法 def f1(self,a): #方法1 return a + 1 def f2(self,b): #方法2 pass def f3(self,c): #方法3 pass
定義好類後,將功能函數(方法)寫在類裏,注意:類裏面的函數有一個必寫值self8指針
#!/usr/bin/env python # -*- coding:utf-8 -*- class fgjk: #定義一個類,在類裏寫函數來實現類的方法 def f1(self,a): #方法1 return a + 1 def f2(self,b): #方法2 pass def f3(self,c): #方法3 pass
self是一個形式參數,這個形式參數是用來,在執行類方法時接收類對象返回值的,9code
注意:類對象的返回值是由python自動當作實參,傳入類方法函數的self,不須要咱們寫,由python自動完成
#!/usr/bin/env python # -*- coding:utf-8 -*- """定義類和類的方法""" class fgjk: #定義一個類,在類裏寫函數來實現類的方法 def f1(self,a): #方法1 print("打印self接收的類對象值",self) return a #返回值 """建立類的對象和是使用類的方法""" a1 = fgjk() #建立類對象賦值給一個變量 print("打印類對象值",a1) #注意:類對象的值是由python自動當作實參,傳入類方法函數的,不須要咱們寫,由python自動完成,至關於下面寫的a1.f1(a1,3) a2 = a1.f1(3) #調用類下面的一個函數傳入參數,來實現一個功能,叫作方法 print("打印返回值",a2) #打印出這個方法的結果 # 輸出 # 打印類對象值 <__main__.fgjk object at 0x0000006685D37160> # 打印self接收的類對象值 <__main__.fgjk object at 0x0000006685D37160> # 打印返回值 3
定義好類和寫好函數方法後,建立這個類的對象賦值給一個變量,經過變量找到這個類下面的功能函數來實現(功能)的方法 , 建立類對象也叫作(建立Foo類的實列)10
#!/usr/bin/env python # -*- coding:utf-8 -*- """定義類和類的方法""" class fgjk: #定義一個類,在類裏寫函數來實現類的方法 def f1(self,a): #方法1 return a + 1 def f2(self,b): #方法2 pass def f3(self,c): #方法3 pass """建立類對象和使用類的方法""" a1 = fgjk() #建立類對象賦值給一個變量 a2 = a1.f1(3) #調用類下面的一個函數傳入參數,來實現一個功能,叫作方法 print(a2) #打印出這個方法的結果 #輸出fgjk類下面的f1()方法 # 4
面向對象原理圖11
封裝12
封裝就是給對象封裝普通字段
面向對象封裝之,在類的對象裏封裝變量和變量值,非主流方法【不推薦】13
就是在類的對象裏封裝變量和變量值,封裝後使用類函數方法時不須要傳值,在類函數方法裏經過self來獲取類對象裏的值便可
給類對象添加變量:建立對象變量.要添加的變量名稱 = 變量值 如a1.zhi = xx
類方法函數獲取對象變量:在方法函數裏經過接收對象的self來獲取,self.添加的類對象變量名稱,這樣就能夠獲取到類對象的值
#!/usr/bin/env python # -*- coding:utf-8 -*- """面向對象封裝之,給類對象封裝變量和變量值""" class fgjk: #定義一個類,在類裏寫函數來實現類的方法 def f1(self): #方法1 b = self.zhi + 5 #獲取類對象裏的zhi變量的值加5 c = b + self.zhi2 #用b結果加類對象裏的zhi2變量值 return c """建立類的對象和使用類的方法""" a1 = fgjk() #建立類對象賦值給一個變量 a1.zhi = 5 #給類對象封裝一個變量和值 a1.zhi2 = 10 #給類對象封裝一個變量和值 a2 = a1.f1() #執行類方法 print(a2) #打印出方法結果 # 輸出 # 20
面向對象封裝之,在類的對象裏封裝變量和變量值原理圖14
__init__()構造方法,面向對象封裝之,給類對象封裝變量和變量值,主流方法 15
__init__(self)類方法函數,若是類裏有定義__init__(self)類方法函數,建立對象後會自動執行__init__(self)方法函數的
使用方法:__init__(self,後面能夠定義變量類接收對象傳值而後封裝到對象)
就是不在從類對象那裏封裝變量和值,從類的__init__(self)方法,向對象封裝變量和值,由於只要建立對象後,python就會默認執行類的__init__(self)方法,然而對象的返回值是自動經過對象傳值給類方法的self形式參數的,因此能夠根據這個形式參數接收到的對象,向對象裏封裝變量和變量值
# -*- coding:utf-8 -*- """面向對象封裝之,給類對象封裝變量和變量值,主流方法""" class fgjk: #定義一個類,在類裏寫函數來實現類的方法 def __init__(self): print(self) self.adc = "你好" #經過self接收到的對象,向對象裏封裝變量和變量值 def f1(self): print(self.adc) """建立類的對象和使用類的方法""" a1 = fgjk() #建立類對象賦值給一個變量,並把類對象返回值傳給類裏面的方法函數的self形式參數 a1.f1() #執行類的方法函數 # 輸出 # <__main__.fgjk object at 0x000000A5E652C518> # 你好
經過類方法的self給對象封裝變量原理圖16
__init__()構造方法,面向對象封裝之,給類對象封裝變量和變量值,主流方法2【推薦】17
# -*- coding:utf-8 -*- """面向對象封裝之,給類對象封裝變量和變量值,主流方法""" a = "變量值" class fgjk: #定義一個類,在類裏寫函數來實現類的方法 def __init__(self,b): print(self) self.adc = b #經過self接收到的對象,向對象裏封裝變量和變量值 def f1(self): print(self.adc) """建立類的對象和使用類的方法""" a1 = fgjk(a) #建立類對象賦值給一個變量,並把類對象返回值傳給類裏面的方法函數的self形式參數 a1.f1() #執行類的方法函數 # 輸出 # <__main__.fgjk object at 0x000000A5E652C518> # 變量值
主流方法2【推薦】原理圖18
注意:咱們通常都是用構造方法2
__del__(self)解釋器銷燬對象時自動調用,咱們只須要知道一些就行,這是python自動完成的,叫作析構方法19
封裝總結20
使用場景,當同一類型的方法具備相同參數時,直接封裝到對象便可
使用場景2:把類當作模板,建立多個對象(每一個對象內封裝的數據能夠不同)
建立類對象,和__init__()構造封裝對象變量,叫作初始化
給對象封裝的變量,叫作給對象建立普通字段
繼承21
繼承就是在定義類b時,能夠在b類名稱後面加上()括號裏寫上另一個a類的名稱,這樣b類就會繼承a類裏的方法22
1.子類(派生類)、繼承父類(基類)中的全部功能23
2.Python類能夠同時繼承多個父類(基類)(c#/Java不能夠)24
3.繼承的優先級,繼承裏有相同方法的優先級25
子類(派生類)、和父類(基類)同時存在一個方法是時,優先找子類(派生類),
若是是一個類繼承了多個類,並且繼承的多個類中有一樣的方法是,優先從子類(派生類)()括號裏的父類(基類)左邊優先
若是是嵌套式繼承,也就是一個類繼承了多個基類,而且多個基類又繼承了多個基類,這時是本身自己類優先,而後是上一級基類左邊第一個優先,再者是左邊第一個基類的上級基類優先,再者是左邊第二基類優先以此類推
也就是說,首先是自身優先,而後是基類左邊優先,而後是基類左邊深度優先,以此類推的
若是嵌套式繼承,最後有兩個類都繼承了同一個基類,這個被兩個類繼承的類不在深度查找,是最後查找這個類的
#!/usr/bin/env python # -*- coding:utf-8 -*- class lei: #定義lei類 def __init__(self,wb = ""): #接收定義lei對象裏的傳值 self.wb = wb #將定義lei對象裏的傳值封裝到lei對象裏 def f1(self): print("f1",self.wb) #打印f1和,lei對象裏封裝的wb變量 def f2(self): print("f2") def f3(self): print("f3") class lei2(lei): #定義lei2類並繼承lei類的方法 def __init__(self,wb2 = ""): #接收定義lei2對象裏的傳值 self.wb2 = wb2 ##將定義lei2對象裏的傳值封裝到lei2對象裏 def j1(self): print("j1") def j2(self): print("j2",self.wb2) #打印j2和,lei2對象裏封裝的wb2變量 def j3(self): print("j3") a = lei("你好") #建立lei類對象,並傳值到lei類__init__方法 a.f1() #執行類裏的f1()方法 b = lei2("我好") #建立lei2類對象,並傳值到lei2類__init__方法 b.f3() #執行lei2類繼承的lei裏的f3()方法 b.j2() #執行lei2類裏的j2()方法 # 輸出 # f1 你好 # f3 # j2 我好
繼承原理圖26
繼承優先級說明圖27
自身優先圖28
基類左邊第一個優先圖29
左邊深度優先圖30
最後有兩個類都繼承了同一個基類,這個被兩個類繼承的類不在深度查找,是最後查找這個類的31
繼承重點,self.XXX()繼承容易錯點,若是一個類繼承了多個基類,而且基類裏有self.XXX()方法,self實際就是建立的對象,self.xxx()就是又回到了建立對象的類裏去找xxx()方法,若是建立的自身類裏沒有xxx()方法,就又從繼承基類的左邊第一個開始查找,在之深度等,以此按照前面說的優先級執行32
#!/usr/bin/env python # -*- coding:utf-8 -*- class a: #定義a類 def __init__(self,zhi = ""): self.zhi = zhi def f1(self): print("a") class b: #定義b類 def __init__(self,zhi = ""): self.zhi = zhi def b1(self): self.f1() class c: #定義c類 def __init__(self,zhi = ""): self.zhi = zhi def f1(self): print("c") class d(b,c,a): #定義d類 def __init__(self,zhi = ""): self.zhi = zhi fsa = d("傳值") #建立d類對象 fsa.b1() #執行d類對象的類裏面的b1()方法,類裏面沒有b1方法,就到繼承的基類左邊第一個b類裏去找b1方法,找到b1方法執行,然而b1裏是執行的對象裏面的f1方法,這樣就又回到了d類裏去找f1方法 # 輸出 # c
self.XXX()繼承原理圖33
super()內置函數【推薦】,在一個類裏獲取上一級父類基類的,__init__方法裏的對象封裝值,注意只能獲取上一級基類的__init__方法裏的對象封裝值34
使用方法:super(子類派生類名稱,self).__init__()
格式:super(b,self).__init__()
#!/usr/bin/env python # -*- coding:utf-8 -*- class c: #定義a類 def __init__(self): self.zf = "狗shi" def f1(self): print("c") class a: #定義a類 def __init__(self): self.zhi = "動物" def f1(self): print("a") class b(a): #定義b類 def __init__(self): self.zh = "貓" super(b,self).__init__() #獲取上一級父類基類的,__init__方法裏的對象封裝值 print(self.zhi) #打印出獲取到的,上一級父類基類的,__init__方法裏的對象封裝值 def b1(self): print("b") c = b() c.f1() # 輸出 # 動物 # a
被獲取類名稱.__init__(self)在一個類裏獲取另一個類的__init__方法裏的對象封裝值,注意,能夠獲取有繼承關係的,也能夠獲取無繼承關係的類35
使用方法:被獲取類名稱.__init__(self)
格式:c.__init__(self)
#!/usr/bin/env python # -*- coding:utf-8 -*- class c: #定義a類 def __init__(self): self.zf = "狗shi" def f1(self): print("c") class a: #定義a類 def __init__(self): self.zhi = "動物" def f1(self): print("a") class b(a): #定義b類 def __init__(self): self.zh = "貓" c.__init__(self) #在一個類裏獲取另一個類的__init__方法裏的對象封裝值,注意,能夠獲取有繼承關係的,也能夠獲取無繼承關係的類 print(self.zf) #打印獲取到的,另一個類的__init__方法裏的對象封裝值 def b1(self): print("b") c = b() c.f1() # 輸出 # 狗shi # a
多態36
多態就是多種形態
python自身支持多態
多態的簡單理解就是,定義一個函數,建立類對象,把類對象當作實際參數傳給函數的形式參數,在函數裏經過形式參數接收到的類對象來執行對象類裏的方法,也就是向函數傳不一樣的對象,就執行不一樣對象類的方法
#!/usr/bin/env python # -*- coding:utf-8 -*- """多態,多種形態""" class ab: #定義ab類 def __init__(self,zhi = ""): #定義__init__方法接收類對象傳的值 self.zhi = zhi #將類對象傳值封裝到對象裏吧,給對象封裝一個字段 def f1(self): #定義類方法 print(self.zhi) #打印ab類對象裏封裝的zhi字段 class cd: #定義cd類 def __init__(self,zhi = ""): #定義__init__方法接收類對象傳的值 self.zhi = zhi #將類對象傳值封裝到對象裏吧,給對象封裝一個字段 def f1(self): #定義類方法 print(self.zhi) #打印cd類對象裏封裝的zhi字段 def ef(fang): #定義一個函數,設置一個形式參數接收類對象 fang.f1() #接收對象,並執行對象的類裏面的f1()方法 ef(ab("你好")) #執行函數,建立ab類對象當作實參傳值給ef函數 ef(cd("我好")) #執行函數,建立cd類對象當作實參傳值給ef函數 # 輸出 # 你好 # 我好
多態原理圖37
面向對象的進階38
成員39
類下面的方法爲類的成員
對象下面的封裝字段爲對象成員
利用反射來操做類裏的成員40
hasattr()內置反射函數,到指定類查找指定方法是否存在,和到指定的對象下查找,對象下的封裝變量是否存在,或者到指定對象查找對象類裏的指定方法,存在返回True,不然返回False
注意:對象有對象指針指向了類,全部也能用hasattr()函數經過對象來查找類裏的方法,因此推薦經過對象來查找,既能夠查找類又能夠查找對象下的字段
使用方法:hasattr(要查找的類名稱或對象名稱,字符串形式要查找的方法名稱或對象封裝名稱)41
格式:hasattr(c,"f1")
到指定類查找指定方法是否存在
#!/usr/bin/env python # -*- coding:utf-8 -*- class c: #定義a類 def __init__(self): self.zf = "狗shi" def f1(self): print("c") class a: #定義a類 def __init__(self): self.zhi = "動物" def f1(self): print("a") fa = hasattr(c,"f1") #hasattr()內置函數,到指定類查找指定方法是否存在,和到指定的對象下查找,對象下的封裝變量是否存在,存在返回True,不然返回False print(fa) # 輸出 # True
到指定的對象下查找對象下的封裝變量是否存在
#!/usr/bin/env python # -*- coding:utf-8 -*- class c: #定義a類 def __init__(self): self.zf = "狗shi" def f1(self): print("c") class a: #定義a類 def __init__(self): self.zhi = "動物" def f1(self): print("a") fa = hasattr(a(),"zhi") #hasattr()內置函數,到指定類查找指定方法是否存在,和到指定的對象下查找,對象下的封裝變量是否存在,存在返回True,不然返回False print(fa) # 輸出 # True
到指定對象查找對象類裏的指定方法
#!/usr/bin/env python # -*- coding:utf-8 -*- class c: #定義a類 def __init__(self): self.zf = "狗shi" def f1(self): print("c") class a: #定義a類 def __init__(self): self.zhi = "動物" def f1(self): print("a") fa = hasattr(a(),"f1") #hasattr()內置函數,到指定類查找指定方法是否存在,和到指定的對象下查找,對象下的封裝變量是否存在,存在返回True,不然返回False print(fa) # 輸出 # True
getattr()內置反射函數,到指定的對象下找到,對象下的封裝變量賦值給一個變量,或者到指定對象找到對象類裏的指定方法賦值給一個變量42
注意:對象有對象指針指向了類,全部也能用hasattr()函數經過對象來查找類裏的方法,因此推薦經過對象來查找,既能夠查找類又能夠查找對象下的字段
使用方法:getattr(要查找的對象,字符串形式要查找的方法名稱或對象封裝名稱)
格式:fa = getattr(c(),"f1")
到指定對象找到對象類裏的指定方法賦值給一個變量,並執行方法
#!/usr/bin/env python # -*- coding:utf-8 -*- class c: #定義a類 def __init__(self): self.zf = "狗shi" def f1(self): print("c") class a: #定義a類 def __init__(self): self.zhi = "動物" def f1(self): print("a") fa = getattr(c(),"f1") #getattr()內置反射函數,到指定的對象下找到,對象下的封裝變量賦值給一個變量,或者到指定對象找到對象類裏的指定方法賦值給一個變量 fa() #執行找到的類方法 # 輸出 # c
到指定的對象下找到,對象下的封裝變量賦值給一個變量
#!/usr/bin/env python # -*- coding:utf-8 -*- class c: #定義a類 def __init__(self): self.zf = "狗shi" def f1(self): print("c") class a: #定義a類 def __init__(self): self.zhi = "動物" def f1(self): print("a") fa = getattr(c(),"zf") #getattr()內置反射函數,到指定的對象下找到,對象下的封裝變量賦值給一個變量,或者到指定對象找到對象類裏的指定方法賦值給一個變量 print(fa) # 輸出 # 狗shi
用反射操做面向對象成員43
根據字符串方式的面向對象模塊,和字符串方式的類方法,用反射來執行面向對象44
面向對象模塊
#!/usr/bin/env python # -*- coding:utf8 -*- class c: #定義a類 def __init__(self): self.zf = "狗shi" def f1(self): print("c") class a: #定義a類 def __init__(self): self.zhi = "動物" def f1(self): print("a222")
反射操做面向對象模塊裏的成員
#!/usr/bin/env python # -*- coding:utf-8 -*- """根據字符串方式的面向對象模塊,和字符串方式的類方法,用反射來執行面向對象""" a = "lib.ska.mk" #面向對象模塊路徑 b = "f1" #類方法名稱 c = __import__(a,fromlist=True) #反射方式導入面向對象模塊 d = hasattr(c.a(),b) #查找模塊裏的a類裏是否有f1方法,返回布爾值 if d: #判斷模塊裏的a類裏是否有f1方法 f1 = getattr(c.a(),b) #若是有就找到f1方法賦值給一個變量 f1() #執行找到a類裏的f1方法 else: print("a類裏沒有f1方法") # 輸出 # a222
靜態字段45
靜態字段,也就是在類裏面定義變量,提供類裏的全部方法調用,這樣能很好的實現多個類有一個相同數據的狀況46
注意:靜態字段是經過,類名稱.靜態字段名稱來訪問的,對象封裝的普通字段,是經過self.普通字段名稱來訪問的
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 shux = "動物" def __init__(self,zhu): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 def f1(self): #定義方法 print(a.shux, self.zhu) #打印類的靜態字段和對象封裝的普通字段 def f2(self): #定義方法 print(a.shux, self.zhu) #打印類的靜態字段和對象封裝的普通字段 def f3(self): #定義方法 print(a.shux, self.zhu) #打印類的靜態字段和對象封裝的普通字段 s = a("貓") #建立對象並傳值 s.f1() #執行對象類裏的f1()方法 f = a("狗") #建立對象並傳值 f.f2() #執行對象類裏的f2()方法 b = a("豬") #建立對象並傳值 b.f3() #執行對象類裏的f3()方法 # 輸出 # 動物 貓 # 動物 狗 # 動物 豬
靜態字段原理圖47
靜態方法48
就是在類裏定義普通函數,函數上面用上裝飾符@staticmethod,靜態方法不須要傳self參數,靜態方法經過類來訪問,不須要建立對象就能夠訪問
@staticmethod在類裏聲明一個靜態方法49
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 @staticmethod #定義靜態方法 def f1(): #靜態方法 print("靜態方法") def f3(self): #定義方法 print(a.shux, self.zhu) a.f1() # 輸出 # 靜態方法
靜態方法原理圖50
類方法51
就是在類裏定義一個函數,函數上面用上裝飾符@classmethod,函數裏有一個必寫形式參數cls用來接收類名稱
@classmethod在類裏聲明一個類方法52
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 @classmethod #定義類方法 def f1(cls): #自動將類名稱傳值給cls形參 print(cls) #打印cls接收到的類名稱 def f3(self): #定義方法 print(a.shux, self.zhu) a.f1() # 輸出 # <class '__main__.a'>
類方法原理圖53
特性方法54
@property特性方法55
就是在類裏定義一個普通方法函數,函數上面用上裝飾符@property,函數裏有一個必寫形式參數self用來接收對象地址,也能夠給方法封裝普通字段
特性方法與普通方法的區別:就是執行特性方法函數時不用寫()括號,特性方法就是將普通方法僞形成經過對象獲取的字段,特殊方法獲取到返回值後是能夠從新賦值的
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 @property #聲明特性方法 def f1(self): #定義特性方法 te = "{}方法".format(self.zhu) print(te) def f3(self): #定義方法 print(a.shux, self.zhu) s = a("特性") s.f1 #執行對象類裏的f1特性方法 # 輸出 # 特性方法
s.f1 = "從新賦值" #特殊方法獲取到返回值後是能夠從新賦值的
特性方法原理圖56
設置特性方法:就是給特性方法設置值57
@方法名稱.setter給特性方法設置值58
就是在類裏的特性方法下面,寫一個給特性方法名稱同樣的方法函數,函數上面用上裝飾符@方法名稱.setter,在方法裏設置一個形式參數來接收,執行設置特性方法傳值,執行設置特性方法時,將特性方法 = 要設置的值便可
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 @property #聲明特性方法 def f1(self): #定義特性方法 te = "{}方法".format(self.zhu) print(te) @f1.setter #設置特性方法 def f1(self,v): #設置特性方法 print(v) #打印設置的特性方法值 self.zhu = v #將設置的特性方法值替換對象封裝的普通字段 s = a("特性") s.f1 #執行對象類裏的f1特性方法 s.f1 = "設置特性方法值" s.f1 # 輸出 # 特性方法 # 設置特性方法值 # 設置特性方法值方法
設置特性方法原理圖59
成員修飾符60
修飾成員的使用權限對成員:靜態字段、普通字段、普通方法、靜態方法、類方法、特性方法,進行成員權限修飾61
公有:就是沒加__修飾符的成員,既能夠在類裏面訪問,也能夠經過類或者對象外部訪問
私有:就是加上__修飾符的成員,經過對象或者類沒法外部訪問,只能在類內部訪問,外部要想訪問必須在類的內部定義一個公有方法,在公有方法裏執行要想訪問的私有成員,經過公有方法來間接的訪問私有成員,注意:一個類的私有方法只有類本身內部能夠使用, 並且沒法被繼承。
__類成員修飾符,用於修飾類的成員私有權限,用了__修飾符的私有成員只有類自身內部能夠訪問。62
靜態字段修飾符63
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 __jt = "靜態字段" def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 def f1(self): print(a.__jt) def f2(self): pass #print(a.__jt) #靜態字段加修飾符後外部不能夠訪問 f = a() #定義對像 f.f1() #能夠經過類裏的f1方法間接訪問 # 輸出 # 靜態字段
普通字段修飾符64
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.__zhu = zhu #將對象傳值封裝到對象裏,封裝普通字段 def f1(self): print(self.__zhu) def f2(self): pass f = a("普通字段") #定義對象 #print(f.zhu) #普通字段加修飾符後外部不能夠訪問 f.f1() #經過類裏的f1方法能夠間接訪問對象裏封裝的普通字段 # 輸出 # 普通字段
普通方法修飾符65
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.__zhu = zhu #將對象傳值封裝到對象裏,封裝普通字段 def __f1(self): print("普通方法") def f2(self): self.__f1() f = a() #定義對象 #f.__f1() #普通方法加修飾符後外部不能夠訪問 f.f2() #經過類裏的f2方法能夠間接訪問加修飾符的f1普通方法 # 輸出 # 普通方法
靜態方法修飾符66
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.__zhu = zhu #將對象傳值封裝到對象裏,封裝普通字段 @staticmethod #定義靜態方法 def __f1(): print("靜態方法") def f2(self): a.__f1() #a.__f1() #靜態方法加修飾符後外部不能夠訪問 f = a() #定義對象 f.f2() #經過類裏的f2方法能夠間接訪問加修飾符的f1靜態方法 # 輸出 # 靜態方法
類方法修飾符67
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.__zhu = zhu #將對象傳值封裝到對象裏,封裝普通字段 @classmethod #定義類方法 def __f1(cls): print("類方法",cls) def f2(self): a.__f1() #a.__f1() #類方法加修飾符後外部不能夠訪問 f = a() #定義對象 f.f2() #經過類裏的f2方法能夠間接訪問加修飾符的f1類方法 # 輸出 # 類方法 <class '__main__.a'>
特性方法修飾符68
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.__zhu = zhu #將對象傳值封裝到對象裏,封裝普通字段 @property #定義特性方法 def __f1(self): print("特性方法") def f2(self): self.__f1 f = a() #定義對象 #f.__f1 #特性方法加修飾符後外部不能夠訪問 f.f2() #經過類裏的f2方法能夠間接訪問加修飾符的f1特性方法 # 輸出 # 特性方法
成員修飾符之特殊手段,外部訪問類的私有成員【不到萬不得已不使用】69
方法:類名稱或者對象名稱._類名稱__私有字段名稱
格式:a._a__jt
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 __jt = "靜態字段" def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 def f1(self): print(a.__jt) def f2(self): pass print(a._a__jt) #特殊手段外部訪問類的私有成員 # 輸出 # 靜態字段
類成員之特殊方法70
__call__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後在對象後面加上()括號,也能夠在對象變量後面加括號是同樣的,會自動執行類裏的__call__方法71
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 def __call__(self, args): #定義__call__方法 print(args,self.zhu) def f2(self): pass f = a("方法")("__call__") # 輸出 # __call__ 方法
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 def __call__(self, args): #定義__call__方法 print(args,self.zhu) def f2(self): pass f = a("方法") f("__call__") # 輸出 # __call__ 方法
__getitem__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後在對象後面加上[]中括號,會自動執行類裏的__getitem__方法,並將[]中括號裏的值傳給__getitem__方法的形式參數。72
注意:對象後面加上[1:2:3],也是執行類的__getitem__方法
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 def __getitem__(self, item): #建立__getitem__方法 s = self.zhu + item #將建立對象封裝的普通字段,加上執行__getitem__方法時的傳值,相加後並返回值 return s #返回值 def f2(self): pass f = a(10) #建立對象傳值 b = f[10] #執行__getitem__方法並傳值給__getitem__方法 print(b) #打印__getitem__方法返回值 # 輸出 # 20
對象後面加上[1:2:3],也是執行類的__getitem__方法 73
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 def __getitem__(self, item): #建立__getitem__方法,將[]中括號裏的數據從新封裝成一個slice對象傳給item print(item) #打印接收到的slice對象元素 def f2(self): pass f = a() #建立對象傳值 b = f[10:12:3] #執行__getitem__方法並傳值給__getitem__方法 print(b) #打印__getitem__方法返回值 # 輸出 # 20
__setitem__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後在對象後面加上[xxx]=xxx中括號等於,會自動執行類裏的__setitem__方法,並將[xxx]=xxx中括號和等於裏的值傳給__setitem__方法的形式參數74
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 def __setitem__(self, key, value): #定義__setitem__方法 print(key,value) #打印[xxx] = xxx 傳值 def f2(self): pass f = a() #建立對象傳值 f["鍵"] = "值" #執行__setitem__方法並傳值給__setitem____方法 # 輸出 # 鍵 值
__delitem__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後在對象後面加上del對象名稱[xxx]中括號,會自動執行類裏的__delitem__方法,並將[xxx]中括號裏的值傳給__delitem__方法的形式參數75
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 def __delitem__(self, key): #定義__delitem__方法 print("刪除",key) #操做[xxx]裏傳來的值 def f2(self): pass f = a() #建立對象傳值 del f["鍵"] #執行__delitem__方法,並傳值給__delitem__方法 # 輸出 # 刪除 鍵
__iter__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後只要for循環對象,會自動執行類裏的__iter__方法,如__iter__方法裏是一個生成器,for循環就會循環出生成器裏的結果76
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __iter__(self): #定義__iter__方法 yield 1 #生成器 yield 2 yield 3 yield 4 def f1(self): pass s = a() #建立對象 for i in s: #循環對象 print(i) #循環打印出生成器裏的數據 # 輸出 # 1 # 2 # 3 # 4
__str__方法是類裏的一個特殊方法,當類裏定義了這個方法時,建立對象後只要print打印對象或者str(對象)時就,會自動執行類裏的__str__方法77
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義類 def __init__(self,vas): #定義__init__方法,接收對象傳值 self.fds = vas #將對象傳值封裝成對象普通字段 def __str__(self): #定義__str__方法 return self.fds #返回對象裏的普通字段 def f1(self): pass f = a("str方法") print(f) #打印對象時自動執行__str__方法 b = str(f) #str(對象)時也會執行__str__方法 print(b) # 輸出 # str方法 # str方法
__dict__查看對象或者類裏的成員78
#!/usr/bin/env python # -*- coding:utf8 -*- class a: #定義a類 def __init__(self,zhu = ""): #初始化__init__接收對象傳值 self.zhu = zhu #將對象傳值封裝到對象裏 def __getitem__(self, item): #建立__getitem__方法,將[]中括號裏的數據從新封裝成一個slice對象傳給item print(item) #打印接收到的slice對象元素 def f2(self): pass f = a("zhi") #建立對象傳值 print(f.__dict__) #查看對象裏的成員 print(a.__dict__) #查看類裏的成員 # 輸出 # {'zhu': 'zhi'} # {'__init__': <function a.__init__ at 0x00000036345AE510>, 'f2': <function a.f2 at 0x00000036345AE620>, '__getitem__': <function a.__getitem__ at 0x00000036345AE598>, '__weakref__': <attribute '__weakref__' of 'a' objects>, '__dict__': <attribute '__dict__' of 'a' objects>, '__module__': '__main__', '__doc__': None}
能夠忽略,源碼建立類原理79
__new__ python建立類源碼方法80
__metaclass__ python建立類源碼方法81
閱讀如下代碼:
class Foo(object): def __init__(self): pass obj = Foo() # obj是經過Foo類實例化的對象
上述代碼中,obj 是經過 Foo 類實例化的對象,其實,不只 obj 是一個對象,Foo類自己也是一個對象,由於在Python中一切事物都是對象。
若是按照一切事物都是對象的理論:obj對象是經過執行Foo類的構造方法建立,那麼Foo類對象應該也是經過執行某個類的 構造方法 建立。
print type(obj) # 輸出:<class '__main__.Foo'> 表示,obj 對象由Foo類建立 print type(Foo) # 輸出:<type 'type'> 表示,Foo類對象由 type 類建立
因此,obj對象是Foo類的一個實例,Foo類對象是 type 類的一個實例,即:Foo類對象 是經過type類的構造方法建立。
那麼,建立類就能夠有兩種方式:
普通方式
class Foo(object): def func(self): print 'hello wupeiqi'
特殊方式(type類的構造函數)
def func(self): print 'hello wupeiqi' Foo = type('Foo',(object,), {'func': func}) #type第一個參數:類名 #type第二個參數:當前類的基類 #type第三個參數:類的成員
==》 類 是由 type 類實例化產生
那麼問題來了,類默認是由 type 類實例化產生,type類中如何實現的建立類?類又是如何建立對象?
答:類中有一個屬性 __metaclass__,其用來表示該類由 誰 來實例化建立,因此,咱們能夠爲 __metaclass__ 設置一個type類的派生類,從而查看 類 建立的過程。
class MyType(type): def __init__(self, what, bases=None, dict=None): super(MyType, self).__init__(what, bases, dict) def __call__(self, *args, **kwargs): obj = self.__new__(self, *args, **kwargs) self.__init__(obj) class Foo(object): __metaclass__ = MyType def __init__(self, name): self.name = name def __new__(cls, *args, **kwargs): return object.__new__(cls, *args, **kwargs) # 第一階段:解釋器從上到下執行代碼建立Foo類 # 第二階段:經過Foo類建立obj對象 obj = Foo()
重點總結82
面向對象三大特性:83
封裝、繼承、多態
成員:84
字段:普通字段(每一個對象都有一份相同數據時)、靜態字段(每一個對象都不一樣的數據時)
方法:靜態方法(無需使用對象封裝的內容時)、類方法(須要獲取對象名稱時)、普通方法(使用對象中的數據時)
特性方法:特性方法(將方法僞形成字段時)
特殊方法:對象後寫上執行屬性,就會自動執行特殊方法
類成員訪問方法:85
經過類訪問的有:靜態字段,靜態方法,類方法
經過對象訪問的有:普通字段,普通方法,特性方法
通常有self的方法用對象訪問,無self的方法用類來訪問
成員修飾符:86
修飾成員的使用權限對成員:靜態字段、普通字段、普通方法、靜態方法、類方法、特性方法,進行成員權限修飾
公有:就是沒加__修飾符的成員,既能夠在類裏面訪問,也能夠經過類或者對象外部訪問
私有:就是加上__修飾符的成員,經過對象或者類沒法外部訪問,只能在類內部訪問,外部要想訪問必須在類的內部定義一個公有方法,在公有方法裏執行要想訪問的私有成員,經過公有方法來間接的訪問私有成員
,注意:一個類的私有方法只有類本身內部能夠使用,並且沒法被繼承。
特殊方法對應的執行屬性:87類名稱(xxx):建立對象並執行類的__init__方法對象變量(xxx):執行類的__call__方法對象變量[xxx]:執行類的__getitem__方法對象變量[x:x:x]:執行類的__getitem__方法對象變量[xxx]=xxx:執行類的__setitem__方法del對象變量[xxx]:執行類的__delitem__方法for循環對象變量:執行類的__iter__方法