一、面向對象的程式設計
面向對象程式設計--Object Oriented Programming,簡稱oop,是一種程式設計思想。
二、面向對象的特性
類:class
類,對比現實世界來說就是一個種類,一個模型。
一個類即是對一類擁有相同屬性的對象的抽象、藍圖、原型。
在類中定義了這些對象的都具備的屬性(variables(data))、共同的方法。
對象:object
對象,也就是指模型造出來的具體的東西。
一個對象即是一個類的執行個體化後執行個體,一個類必須經過執行個體化後方可在程式中調用,一個類可以執行個體化多個對象,每個對象亦可以有不同的屬性,就像人類是指所有人,每個人是指具體的對象,人與人之前有共性,亦有不同。
執行個體化:
初始化一個類,造了一個對象。把一個類變成一個具體的對象的過程,叫做執行個體化。
以下是一段小代碼講解執行個體化和調用
1 class BuyCar(object):
2 def sale(self):
3 print('賣車')
4 return 100
5 def insurance(self):
6 print('買保險')
7 def check(self):
8 print('驗車')
9 def card(self):
10 print('選牌')
11 def pay(self):
12 print('付款')
13 def done(self):
14 print('上牌完成')
15
16 me = BuyCar()
17 #執行個體化
18 r = me.sale()
19 接收函數傳回值
20 print(r)
21 me.check()
22 me.card()
23 me.pay()
24 me.done()
# 如果是函數名加括号的話,調用函數
# 如果是類名加括号的話,執行個體化對象
封裝:
把一些功能的實作細節不對外暴露,類中對資料的指派、内部調用對外部使用者是透明的,這使類變成了一個膠囊或容器,裡面包含着類的資料和方法。
比如說造的一個人,你把他身體内部的什麼心肝脾肺腎都封裝起來了,其他人都看不到,你直接找這個人。
繼承:
一個類可以派生出子類,在這個父類裡定義的屬性、方法自動被子類繼承。比如說你繼承了你父親的姓。
python3中多繼承都是廣度優先,python2中經典類的多繼承是深度優先,新式類的多繼承是按照廣度優先的。
繼承是為了代碼的重用
多态:
對不同類的對象發出相同的消息将會有不同的行為。比如,你的老闆讓所有員工在九點鐘開始工作, 他隻要在九點鐘的時候說:“開始工作”即可,而不需要對銷售人員說:“開始銷售工作”,對技術人員說:“開始技術工作”, 因為“員工”是一個抽象的事物, 隻要是員工就可以開始工作,他知道這一點就行了。至于每個員工,當然會各司其職,做各自的工作。
多态就是抽象化的一種展現,把一系列具體事物的共同點抽象出來, 再通過這個抽象的事物, 與不同的具體事物進行對話。
一種接口,多種實作。
三、類
一些概念:
屬性:屬性就是類裡面的一個變量,有類變量和執行個體變量,類變量是類在定義的時候就有的,執行個體變量是在執行個體化的時候才産生的變量。這個可以了解為,人是一個類,他的名字、年齡、性别就是它的屬性。
方法:方法就是類的功能,也就是定義在類裡面的函數,它實作了某個功能,比如說人有睡覺的功能。
構造函數:什麼是構造函數,就是類在執行個體化的時候做的某些初始化操作,比如說人,你造一個汽車的時候,它得有顔色、型号等等。
析構函數:析構函數就是這個執行個體在銷毀的時候做的一些操作。
定義類:
定義類使用class關鍵字,類名一般我們開發的時候首字母要大寫。python中有經典類和新式類,他倆在python3中沒有差別,在python2中經典類在多繼承的時候是深度優先,新式類是廣度優先。python3中統一是廣度優先,這個後面在說繼承的時候會說。
1 class Cay(object):
2 # wheel = 4
3 #類變量,所有的執行個體都可以使用
4 def __del__(self):
5 # 析構方法
6 # 作用是對象被銷毀時執行
7 # 這個執行個體被銷毀的時候執行的,也就是不在記憶體裡面
8 print('over、、、')
9 def __init__(self,color,pl,pz):
10 #構造方法,是類在執行個體化對象的做的操作
11 #如果你想在類初始化的給它傳一些參數,那麼就要在
12 #構造方法裡面寫參數
13 self.color = color
14 #給執行個體化的對象添加屬性
15 # 對象的color等于我傳進來的color
16 self.pl = pl
17 self.pz = pz
18 # 這些都是執行個體變量
19 def run(self):
20 print('run')
21 print('汽車的顔色是:',self.color)
22 def driver(self):
23 #self就是代表執行個體化之後的這個對象,為了節省記憶體
24 #代表本類對象
25 print('driver')
26 def movie(self):
27 print('movie')
28 def p(self):
29 self.wheel = 8
30 print(self.wheel)
31
32 ywn_car = Cay('red','5.0','悍馬')
33 ywn_car.p()
34 ywb_car = Cay('red','5.0','悍馬')
35 # print(ywb_car.wheel)
1.在此處說明一下self。在我們進行執行個體化的時候可以無窮無盡的執行個體化對象,在這個類裡面所有的對象都有run,driver,movie和
p的功能,所有的功能都是一樣的,但是這些color,pl,pz的屬性可以是不一樣的,如果每個對象執行個體化的時候都儲存一遍這些公共
沒變的東西就會特别浪費記憶體,就不需要對每一個執行個體化對象的時候對公共的功能進行定義。
那麼如果不定義的話怎麼知道究竟是誰調用的這些方法呢?是以用到了self。誰調用的話把誰傳進去就行了。這樣的話就知道是誰調用了。
是以把self傳進去,self就是代表執行個體化之後的這個對象,使用self是為了節省記憶體。self作為必填參數在調用的時候不需要傳,自動
會把這個對象加進去。也就是self代表的是本類對象.
2.__init__。這個叫做構造方法,實在類的執行個體化的時候做的操作,如果你想在類初始化的時候就給它傳一些參數就要用到__init__了。
比如說我造汽車,你不給我說我哪知道你要什麼樣的汽車,是以這些東西你必須要先跟我說,想要實作這個就要使用__init__。
在self裡面的寫的東西,不論在哪都能用點能點出來
3.object是基類。執行個體化,在記憶體中存儲,都是通過object來實作的
4.__del__。這個叫做析構方法,執行個體被銷毀時所執行的。當程式執行完,對象才會被銷毀掉。那麼這個方法什麼時候能用到呢?比如在關資料庫連接配接的時候,當資料庫不用了
的時候這個類運作後就會自動關了。
5.類變量:在類裡面定義的變量就是類變量,類變量是所有的執行個體變量都能用,相當于公共的。用的時候還是self.wheel,和執行個體變量一樣
通過下面這段代碼介紹一下私有方法和私有變量,變量名前面加兩個下劃線就是私有變量,方法名前面加兩個下劃線就是私有變量.
1 import xlrd
2 class ReadCase(object):
3 __name='haha'
4 # 私有變量
5 # 類變量,隻能在類裡面通路,出了類就不行了
6 def __init__(self,f_name):
7 self.fname=f_name
8 def __set(self):
9 self.money=1999999
10 # 私有方法就是在函數名前面加倆下劃線,隻能在類裡面調用,出了類通路不了
11 print('這個是私有方法:',self.money)
12 def read_case(self):
13 self.__set()
14 # book=xlrd.open_workbook(self.fname)
15 print('私有變量name的值:',self.__name)
16 self.__name='panyang'
17 print('私有變量name的值:', self.__name)
18 r=ReadCase('a.xls')
19 # print(r.__name) 這句報錯
20 r.read_case()
21 # print(r.name)
22 r.__set()
23 # 私有變量隻能在類裡面使用,出了類就不能用了
24 # 所有的私有方法和私有類,出了這個類就用不了了
面向對象的三大特點:封裝,繼承,多态
封裝:就相當于給你封裝好了功能,你看不見,隻能用.
繼承:
繼承就是父類有的方法,子類都可以用。看一下下面這段代碼:
1 class Person(object):
2 def __init__(self,name,sex):
3 self.name=name
4 self.sex=sex
5 def Cry(self):
6 print('%s[哭]'%self.name)
7 class Man(Person):
8 def Work(self):
9 print('working')
10 class Women(Person):
11 def shopping(self):
12 print('shopping')
13 class Children(Man,Women): # 多繼承
14 pass
15 panyang=Women('panyang','nv')
16 panyang.shopping()
17 panyang.Cry()
那麼問題來了,如果繼承的兩個父類有相同的屬性,那繼承的是哪個父類的屬性呢?看下面的代碼:
1 class A(object):
2 def say(self):
3 print('A')
4 class B(A):
5 def say(self):
6 print('B')
7 class C(A):
8 def say(self):
9 print('c')
10 class D(C, B):
11 pass
12 d = D()
13 d.say()
python3裡面多繼承的時候,都是廣度優先
python2裡面多繼承的時候,如果用的是經典類,那麼是深度優先;如果是新式類的話,是廣度優先。深度優先和廣度優先會在下一篇部落格裡面說到。
多态:
在python裡面沒有多态,不能直接實作多态,但是可以間接實作多态,代碼如下:
1 class Person(object):
2 def __init__(self,name,sex):
3 self.name=name
4 self.sex=sex
5 def Cry(self):
6 print('%s[哭]'%self.name)
7 class Man(Person):
8 def Work(self):
9 print('working')
10 class Women(Person):
11 def shopping(self):
12 print('shopping')
13 class Children(Man,Women):
14 pass
15 panyang=Women('panyang','nv')
16 panyang.shopping()
17 panyang.Cry()
18 python間接實作多态
修改父類的方法:
1 class Animal(object):
2 def __init__(self,name):
3 self.name = name
4 print('這個是animal裡面的init')
5 class Cat(Animal):
6 def speak(self):
7 print('喵喵喵')
8 class Dog(Animal):
9 #在父類方法的基礎上添加新功能
10 def __init__(self,name,color):
11 # 在重寫父類方法的時候,先要調用一下父類的這個方法
12 把父類裡面的方法重寫了,如果子類裡面重寫了父類的方法就直接調用子類重寫的方法
13 Animal.__init__(self,name)
14 #把父類裡面的方法重寫
15 #如果子類裡面重寫了父類的方法,那麼直接調用子類的重寫後的方法
16 self.color = color
17 def speak(self):
18 print('【%s】汪汪汪'%self.name,self.color)
19 xh = Dog('小黑','black')
20 xh.speak()
21 一種方法,多種實作
22 c1 = Cat()
23 d1 = Dog()
24 obj = [c1,d1]
25 for i in obj:
26 i.speak()
下面再說一下靜态方法和類方法:
1 class Stu(object):
2 country = 'china' # 類變量
3 def __init__(self, name):
4 self.name = name
5 @staticmethod
6 # 靜态方法和普通的函數沒有任何差別,隻不過是寫在類裡面而已
7 # 靜态方法,和類本身沒有什麼關系了,就相當于在類裡面定義了一個方法而已
8 def say():
9 print('xxx')
10 @classmethod
11 # 類方法
12 # 靜态方法,和類方法不同的是,它可以使用類變量,必須要傳一個值,代表的就是這個類
13 def hello(cls):
14 print(cls.country)
15 def hi(self):
16 # 這個是執行個體方法
17 print(self.name)
18 t = Stu('name')
19 Stu.hello()
20 Stu.say()
21 t.hi() # 類方法可以不進行執行個體化,直接調用
22 t.say()
23 t.hello()