學習筆記九 面向物件程式設計
一.面向物件技術簡介:
- 類(Class): 用來描述具有相同的屬性和方法的物件的集合。它定義了該集合中每個物件所共有的屬性和方法。物件是類的例項。
- 類變數:類變數在整個例項化的物件中是公用的。類變數定義在類中且在函式體之外。類變數通常不作為例項變數使用。
- 資料成員:類變數或者例項變數用於處理類及其例項物件的相關的資料。
- 方法重寫:如果從父類繼承的方法不能滿足子類的需求,可以對其進行改寫,這個過程叫方法的覆蓋(override),也稱為方法的重寫。
- 例項變數:定義在方法中的變數,只作用於當前例項的類。
- 繼承:即一個派生類(derived class)繼承基類(base class)的欄位和方法。繼承也允許把一個派生類的物件作為一個基類物件對待。例如,有這樣一個設計:一個Dog型別的物件派生自Animal類,素以Dog也是一個Animal。
- 例項化:建立一個類的例項,類的具體物件。
- 方法:類中定義的函式。
- 物件:通過類定義的資料結構例項。物件包括兩個資料成員(類變數和例項變數)和方法。
二.類:
三種定義類的方式:
class My: #經典類 pass class My2(object): #新式類 pass class My3(): #新式類 pass
簡單例子:定義一個叫MyDb資料庫操作類,裡面包含資料庫的一些方法。
1 class MyDb: 2 def __init__(self,host,user,password,db,port=3306,charset='utf8'):#建構函式, 3 print('連線資料庫') 4 self.conn = pymysql.connect(host=host,user=user,password=password, 5 db=db,port=port,charset=charset) 6 self.cur = self.conn.cursor() 7 8 def execute_one(self,sql): 9 print('返回單條資料') 10 self.cur.execute(sql)11 res = self.cur.fetchone() 12 return res 13 14 def execute_many(self,sql): 15 print('返回多條資料的') 16 self.cur.execute(sql) 17 res = self.cur.fetchall() 18 return res 19 20 def __del__(self):#解構函式 21 print('關閉資料庫連線') 22 self.cur.close() 23 self.conn.close() 24 25 my = MyDb('192.168.1.40','jxz','123456','jxz') #例項化 26 27 #一個變數前面加了self之後,那麼在這個類裡面的其他的函式都可以用了。 28 29 res = my.execute_one('select * from app_myuser where username="testuser1";') 30 print(res) 31 32 res2 = my.execute_many('select * from app_myuser limit 10;') 33 34 print(res2)
其中__init__和__del__分別是建構函式和解構函式。建構函式是在例項化時候被呼叫,一般都是為這個例項化物件賦初始值,解構函式是在這個物件生命週期結束的時候呼叫。他們預設都是自動呼叫。但是也有顯示呼叫。
__init__()方法是可選的,如果不提供,Python 會給出預設的__init__方法。
__del__()也是可選的,如果不提供,則Python 會在後臺提供預設解構函式如果要顯式的呼叫解構函式,可以使用del關鍵字,方式如下:
del 物件名 三.例項方法,類方法,靜態方法,屬性方法,私有方法:1 class Car: 2 wheel = 4 #類變數 3 def __init__(self,color,p): 4 self.color = color #例項變數 5 self.p = p 6 7 def help(self): 8 print('汽車有%s個輪子'%self.wheel) 9 print('汽車的顏色是%s'%self.color) 10 print('牌子%s'%self.p) 11 print('='*10) 12 self.haha() 13 self.check_wheel() 14 15 @classmethod 16 def check_wheel(cls):#類方法 17 print('cls的記憶體地址',id(cls)) 18 print(cls.wheel) 19 cls.haha() 20 21 @classmethod 22 def haha(cls): 23 print('哈哈哈') 24 cls.help2() 25 26 @staticmethod 27 def help2():#靜態方法 28 print('這個類的作用是造汽車,它裡面有xxx方法') 29 30 @property 31 def yesterday(self):#屬性方法 32 import datetime 33 res = datetime.date.today() + datetime.timedelta(-1) 34 return str(res) 35 36 def tom(self): 37 import datetime 38 res = datetime.date.today() + datetime.timedelta(1) 39 return str(res)
例項屬性:類裡的例項方法的第一個引數必須為self,這是例項方法的唯一標誌。可以理解為self就是例項本身,因此例項方法必須在例項化後才可以呼叫(因為不例項化就是不存在的)。各個例項有自己獨立的例項空間,存放自己的例項屬性(變數和方法)。所以在例項化後,可以新增例項屬性(例項變數)。例項方法裡面可以隨便通過self來呼叫例項方法,類方法,靜態方法,類變數。
類屬性:包括方法和變數,類方法必須由@classmethod裝飾,並且方法的第一個引數必須是cls,不需要例項化就可以呼叫,類屬性的空間和例項屬性的空間是獨立的,一個類的屬性空間只有一個,雖然類屬性可以被其他物件訪問,但是由於空間獨立,類屬性只能由類自己修改,例項可以訪問,無權修改。
1 Car.help2() 2 mcb = Car('赤橙黃綠青藍紫','馬春波') 3 print(mcb.wheel)#例項沒有定義wheel的時候,預設使用類變數 4 mcb.wheel=8 5 print(mcb.wheel)#當例項定義了自己的wheel屬性的時候,使用的就是自己的wheel 6 print(Car.wheel)
結果:
這個類的作用是造汽車,它裡面有xxx方法
4
8
4
要注意的是:例項名.類屬性和類名.類屬性是兩個獨立的空間,值互不影響。
靜態方法:不需要例項化就可以呼叫的,它就是一個定義在類裡面的普通函式,不能使用例項變數、例項方法、不能使用類變數、類方法。用@staticmethod裝飾,沒有必寫引數。一般用來列印資訊。
私有方法:變數、函式,前面加兩個下劃線就代表是一個私有的,只能在類裡面用。在類外面就不能使用,只能通過類方法或者例項方法去修改。出於安全考慮,就是提供了修改或操作的接口才能進行修改,否則其他無權修改。
1 class My: 2 def test(self): 3 self.__password = 123456 4 def say(self): 5 print('password',self.__password) 6 def __set_password(self): 7 self.__password = 7890 8 def update(self): 9 self.__set_password() 10 11 m = My() 12 m.test() 13 m.say() 14 m.update() 15 m.say()
password 123456
password 7890
屬性方法:用@property裝飾,改方法不允許帶引數,例如上述的yesterday(),作用就是在呼叫的時候省去括號,比如這個方法呼叫就是print(mcb.yesterday)。
四.繼承:
子類可以繼承父類的方法而無需重新定義他們。繼承最大的好處是子類獲得了父類的全部功能。當然,也可以對子類增加一些方法。或者重寫父類的方法。
class Lm: money = 1000000 house = 5 def driver(self): print('會開車') class Mcb(Lm): def about_me(self): print('我有 %s 錢 ,%s 房子'%(self.money,self.house)) self.driver() def driver(self):#方法過載 print('會開28個輪子的汽車') m = Mcb() m.driver() m.about_me()
會開28個輪子的汽車 我有 1000000 錢 ,5 房子 會開28個輪子的汽車