def 函數名(參數): pass class 類名: def 函數名(self,參數): # self必填 pass z1 = 類名() # 這時,調用對象 z1,self參數即爲 z1
例1:python
class bar: def foo(self,arg): print(self,arg) z1 = bar() print(z1) # <__main__.bar object at 0x0000019BC3088D30> z1.foo('wjz') # <__main__.bar object at 0x0000019BC3088D30> wjz z2 = bar() print(z2) # <__main__.bar object at 0x0000019BC306B358> z2.foo('wjk') # <__main__.bar object at 0x0000019BC306B358> wjk
從上面的例子能夠看出,self 就是當前調用的對象(即便後面繼承時);web
例2:數據庫
class bar: def foo(self,arg): print(self.job,arg) z1 = bar() z1.job = 'IT' z1.foo('wjz') # IT wjz z2 = bar() z2.job = 'IT' z2.foo('wjk') # IT wjk
從上面能夠看出,當向對象存儲變量時,它會把該變量傳給類裏面的方法;編程
構造方法:函數式編程
當 obj = 類名() 時,其實是作了兩件事: 在內存中開闢空間,建立對象; 經過對象,自動執行了一個方法:__init__方法(別名:構造方法)。
把公用的變量封裝到init方法中。 例如:函數
class DataBaseHelper: def __init__(self,ip,port,username,password): self.ip = ip self.port = port self.username = username self.password = password def insert(self): pass def delete(self): pass def update(self): pass def select(self): pass
適用場景:若是多個函數都用一些共同參數,則適合面向對象來作。例如上面數據庫操做;spa
舉例:指針
class f: def f1(self): print("in the f.f1") class s(f): #這裏加一個括號,指明該類的父類(基類);子類(派生類)會繼承父類的方法;s類中找不到發方法,會去f類中找。 def s1(self): print("in the s.s1") def f1(self): super(s,self).f1() # 這裏super(s,self) 表示是s的父類; f.f1(self) # 這個等效上面這句 super(s,self).f1();注意,必定不能忘記self print("in the s.f1") z = s() z.f1()
多繼承: 若是子類繼承多個父類,則排在前面的父類優先;如:code
class father1: def a1(self): print("in the f1.a1") class father2: def a1(self): print("in the f2.a1") class son(father1,father2): # father1在前面,優先繼承; def s1(self): print("in the son.s1") z = son() z.a1() # 等效 son.a1(z) 打印 in the f1.ar 此時,father1和father2都有a1方法,而且son的父類有兩個,則按順序優先。
上面例子中,假如father1中沒有a1方法,而father2有。可是father1的父類有a1,則繼續在father1的父類中查找。都沒有時,纔會去father2。可是,若是father0是father1和father2共同的父類,則會最後繼承共同的父類。如圖:對象
python中,原生多態。這個不重要,先忽略吧。
類(class)的成員有字段、方法;其實還有一個屬性
在類中定義的變量,稱爲靜態字段,屬於類,保存在類中,能夠經過類或者對象訪問;
在類中的方法中定義的字段,稱爲普通字段,屬於對象,保存在對象中,只能經過對象訪問;
以下:
class make: port = 22 # 靜態字段 def __init__(self,ip,username,passwd): self.ip = ip # 普通字段 self.username = username self.passwd = passwd z1 = make('1.1.1.1','root','123456') print(z1.ip,z1.username,z1.passwd,z1.port) # 打印 1.1.1.1 root 123456 22 z2 = make('2.2.2.2','admin','admin') print(z2.ip,z2.username,z2.passwd,z2.port) # 打印 2.2.2.2 admin admin 22 print(make.port) # 打印 22 可見,靜態字段屬於類,同時也能夠經過類對應的對象取得(由於對象經過類對象指針指向該類)。
構造方法:在上面面向對象三大特性之封裝章節已經提到,即init方法;self是必須的;
普通方法:和構造方法同樣,只是名字不是 init的方法就是普通方法;由對象調用,也能夠經過類進行調用(必須指定self對象),self是必須的;
靜態方法:在普通方法前面加上裝飾器 staticmethod,便是靜態方法;可是有個區別:self不是必須的;普通方法調用時,self就是當前調用對象;而靜態方法中,若是指定了self,則必須指定self才能夠;由類或對象(對象調用實際上是根據類對象指針,經過類進行調用)調用;
類方法:在普通方法前面加上裝飾器 classmethod,便是類方法;類方法中,通常不使用self,而是寫成 cls,cls爲當前類;由類直接調用;類方法和靜態方法沒有太大區別;
例如:
class make: def __init__(self): # 構造方法 pass def upload(self): # 普通方法 pass @staticmethod def status(self): # 靜態方法,self不是必須的,能夠不要self; pass @classmethod def classmd(cls): # 類方法,這裏通常寫cls print(cls) pass make.classmd() # 打印結果和 print(make)同樣。
說類的成員有兩種。其實還有一種,定義像方法,調用像字段;咱們叫它 屬性
這種屬性還能夠修改、刪除;其實並非真的刪除,只是僞造字段的操做(修改、刪除)
class make: @property def its(self): # 定義屬性,若是定義了property以後,後面還有getter,則優先執行getter;若是沒有定義getter,則調用時執行property print("property") return 1 @its.getter def its(self): # 優先級高於property; print("getter") @its.setter def its(self,value): # 定義屬性its能夠修改 print(value,"setter") @its.deleter def its(self): # 定義屬性its能夠刪除 print("delete") obj = make() r = obj.its # obj.its像是調用字段,可是its定義時像方法; print(r) # 返回 1 obj.its = 123456 # 看似是更改,實際上是找到 its.setter,而後執行。123456當作參數傳給 its.setter del obj.its # 看似是刪除,實際上是找到its.deleter,而後執行
在上面的基礎上補充:
class make: @property def f1(self): print("in the f1") return 123 @f1.getter def f1get(self): print("in the f1getter") return 00 @f1.setter def f1set(self,value): print("in the f1setter",value) return 11 @f1.deleter def f1del(self): print("in the f1deleter") return 22 @f1get.fget # 這裏能夠執行 @property修飾的方法f1; def f2(self): print("in the f2") return 456 @f1set.fset def f3(self): print("in the f3") return 789 @f1del.fdel def f4(self): print("in the f4") return 000
咱們不調用類,只是定義這個類,這時:
@f1get.fget 會自動執行 f1get方法;
@f1set.fset 會自動執行 f1set方法;
@f1del.fdel 會自動執行 f1del方法;
三個是相同的原理,注意:fget能夠執行 property、getter的對象;fset只能夠執行setter的對象;fdel只能夠執行deleter的對象。
這裏就拿fget舉例:
另外:
def f1(self): return 123 per = property(fget=f1) ------ 上下兩部分等效 ------ @property def per(self): return 123
同理,
class make: def f1(self): print("in f1") return 123 def f2(self,val): print("in f2",val) return 456 per = property(fget=f1,fset=f2) # 這裏就是關鍵字參數,fget/fset能夠省略,就是位置參數;即,fget、fset、fdel順序。property(fget,fset,fdel,doc="描述") z = make() z.f1 = 123 ------ 上下兩部分等效 ------ class make: @property def f1(self): print("in f1") return 123 @f1.setter def f1(self,val): print("in f2",val) return 456 z = make() z.f1 = 123