天天看點

python學習筆記--面向對象的程式設計和類

一、面向對象的程式設計
    面向對象程式設計--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()