標籤:nim 也會 car -o 物件導向編程 lis 介面 組合 並且
一、物件導向編程
物件導向--Object Oriented Programming,簡稱oop,是一種程式設計思想。在說物件導向之前,先說一下什麼是編程範式,編程範式你按照什麼方式來去編程,去實現一個功能。舉個例子,你要做飯,可以用電磁爐,也可以用瓦斯灶。不同的編程範式本質上代表對各種類型的任務採取的不同的解決問題的思路,兩種最重要的編程範式分別是面向過程編程和物件導向編程。
提到物件導向,就不得不提到另一種編程思想,面向過程;什麼是面向過程呢,面向過程的思想是把一個項目、一件事情按照一定的順序,從頭到尾一步一步地做下去,先做什麼,後做什麼,一直到結束。這種思想比較好理解,其實這也是一個人做事的方法,我們之前編程的思想也都是使用這種思想。這種編程思想,只要前面有一個步驟變了,那麼後面的就也要變,後面維護起來比較麻煩,這樣的編程思想,我們在寫一些簡單的小程式、只執行一次的指令碼時可以使用。而物件導向呢,物件導向的思想是把一個項目、一件事情分成更小的項目,或者說分成一個個更小的部分,每一部分負責什麼方面的功能,最後再由這些部分組合而成為一個整體。這種思想比較適合多人的分工合作,就像一個大的機關,分各個部門,每個部門分別負責某樣職能,各個部門可以充分發揮自己的特色,只要符合一定前提就行了。
舉個例子:比如剛才說的一個大的機關,要做某一個項目,從面向過程的思想來說,應該是這樣分析的,先怎麼樣,再怎麼樣,最後怎麼樣。第一樣應該如何完成,第二樣應該如何完成等等。等到每一步驟都完成,項目也就完成了。而物件導向的思想則應該是這樣想的,這個項目是由幾個部分組成的,我們就做好分工,成立一個部門來做一個部分的功能,另一個部門來做另一個部分。各個部門可以不用理解其他部門的事,只要完成自己那一部分的事情就OK了。
二、物件導向的特性
類:class
類,對比現實世界來說就是一個種類,一個模型。
一個類即是對一類擁有相同屬性的對象的抽象、藍圖、原型。
在類中定義了這些對象的都具備的屬性(variables(data))、共同的方法。
對象:object
對象,也就是指模型造出來的具體的東西。
一個對象即是一個類的執行個體化後執行個體,一個類必須經過執行個體化後方可在程式中調用,一個類可以執行個體化多個對象,每個對象亦可以有不同的屬性,就像人類是指所有人,每個人是指具體的對象,人與人之前有共性,亦有不同。
執行個體化:
初始化一個類,造了一個對象。把一個類變成一個具體的對象的過程,叫做執行個體化。
封裝:
把一些功能的實現細節不對外暴露,類中對資料的賦值、內部調用對外部使用者是透明的,這使類變成了一個膠囊或容器,裡麵包含著類的資料和方法。
比如說造的一個人,你把他身體內部的什麼心肝脾肺腎都封裝起來了,其他人都看不到,你直接找這個人。
繼承:
一個類可以派生出子類,在這個父類裡定義的屬性、方法自動被子類繼承。比如說你繼承了你父親的姓。
python3中多繼承都是廣度優先,python2中經典類的多繼承是深度優先,新式類的多繼承是按照廣度優先的。
繼承是為了代碼的重用
多態:
對不同類的對象發出相同的訊息將會有不同的行為。比如,你的老闆讓所有員工在九點鐘開始工作, 他只要在九點鐘的時候說:“開始工作”即可,而不需要對銷售人員說:“開始銷售工作”,對技術人員說:“開始技術工作”, 因為“員工”是一個抽象的事物, 只要是員工就可以開始工作,他知道這一點就行了。至於每個員工,當然會各司其職,做各自的工作。
多態就是抽象化的一種體現,把一系列具體事物的共同點抽象出來, 再通過這個抽象的事物, 與不同的具體事物進行對話。
一種介面,多種實現。
三、物件導向的好處
對於程式設計語言的初學者來講,OOP不是一個很容易理解的編程方式,大家雖然都按老師講的都知道OOP的三大特性是繼承、封裝、多態,並且大家也都知道了如何定義類、方法等物件導向的常用文法,但是一到真正寫程式的時候,還是很多人喜歡用函數式編程來寫代碼,特別是初學者,很容易陷入一個窘境就是“我知道物件導向,我也會寫類,但我依然沒發現在使用了物件導向後,對我們的程式開發效率或其它方面帶來什麼好處,因為我使用函數編程就可以減少重複代碼並做到程式可擴充了,為啥子還用物件導向?”對於此,我個人覺得原因應該還是因為你沒有充分瞭解到物件導向能帶來的好處。
無論用什麼形式來編程,我們都要明確記住以下原則:
寫重複代碼是非常不好的低級行為
你寫的代碼需要經常變更
開發正規的程式跟那種寫個運行一次就扔了的小指令碼一個很大不同就是,你的代碼總是需要不斷的更改,不是修改bug就是添加新功能等,所以為了日後方便程式的修改及擴充,你寫的代碼一定要遵循易讀、易改的原則(專業資料叫可讀性好、易擴充)。
如果你把一段同樣的代碼複製、粘貼到了程式的多個地方以實現在程式的各個地方調用,這個功能,那日後你再對這個功能進行修改時,就需要把程式裡多個地方都改一遍,這種寫程式的方式是有問題的,因為如果你不小心漏掉了一個地方沒改,那可能會導致整個程式的運行都 出問題。 因此我們知道 在開發中一定要努力避免寫重複的代碼,否則就相當於給自己再挖坑。
還好,函數的出現就能幫我們輕鬆的解決重複代碼的問題,對於需要重複調用的功能,只需要把它寫成一個函數,然後在程式的各個地方直接調用這個函數名就好了,並且當需要修改這個功能時,只需改函數代碼,然後整個程式就都更新了。
其實OOP編程的主要作用也是使你的代碼修改和擴充變的更容易,那麼小白要問了,既然函數都能實現這個需求了,還要OOP幹毛線用呢? 呵呵,說這話就像,古時候,人們打仗殺人都用刀,後來出來了槍,它的主要功能跟刀一樣,也是殺人,然後小白就問,既然刀能殺人了,那還要槍幹毛線,哈哈,顯而易見,因為槍能更好更快更容易的殺人。函數編程與OOP的主要區別就是OOP可以使程式更加容易擴充和易更改。
四、類
一些概念:
屬性:屬性就是類裡面的一個變數,有類變數和執行個體變數,類變數是類在定義的時候就有的,執行個體變數是在執行個體化的時候才產生的變數。這個可以理解為,人是一個類,他的名字、年齡、性別就是它的屬性。
方法:方法就是類的功能,也就是定義在類裡面的函數,它實現了某個功能,比如說人有睡覺的功能。
建構函式:什麼是建構函式,就是類在執行個體化的時候做的某些初始化操作,比如說人,你造一個汽車的時候,它得有顏色、型號等等。
解構函式:解構函式就是這個執行個體在銷毀的時候做的一些操作。
定義類:
定義類使用class關鍵字,類名一般我們開發的時候首字母要大寫。python中有經典類和新式類,他倆在python3中沒有區別,在python2中經典類在多繼承的時候是深度優先,新式類是廣度優先。python3中統一是廣度優先,這個後面在說繼承的時候會說。
class Car():#模型,模板def __del__(self):#解構函式,這個執行個體被銷毀的執行的。print(‘over..‘)def my_self(self):print(‘我是一個汽車 我的顏色是【%s】,我有【%s】個窗戶‘%(self.color,self.window))self.price = 10002def run(self):print(self.color)print(self.window)print(self.price)print(‘汽車在跑。。。‘)def __init__(self,color,window):##建構函式,是類在初始化的時候會執行它#如果你的類在執行個體化的時候要傳入一些參數,那麼你就要在__init__這個函數裡寫參數了self.color = color #綁定屬性self.window = windowprint(‘執行我了。。‘)#把模型做成實際的一個汽車,這個過程叫做執行個體化。bus = Car(‘黃色‘,‘3開門‘) #執行個體化bus2 = Car(‘黑色‘,‘4開門‘) #執行個體化bus3 = Car(‘粉色‘,‘2開門‘) #執行個體化bus.my_self() #bus2.my_self()bus3.my_self()#執行個體就是指具體造出來的東西,通過類執行個體化處理的東西,就是執行個體#對象,就是執行個體
繼承:
class F(object): ‘‘‘ 這個是父類 ‘‘‘ def __init__(self,name,sex): self.name = name self.sex = sex def info():#方法 print(‘name is %s sex is %s ‘%(self.name,self.sex)) class S(F):#繼承F這個類 pass s1 = S(‘牛牛‘,‘男‘)#執行個體化子類 s1.info()#因為繼承父類,所以父類的方法他都有 那如果在父類裡面有一個方法,子類裡面也有的話,但是子類想重寫一下父類的方法,增加新功能下面這麼寫: class test(): def __init__(self,name): self.name = name class test1(test): def __init__(self,name,age): # test.__init__(self,name)#修改父類的方法,這個是經典類裡面的寫法 super(test1,self).__init__(name)#和上面的效果一樣,這個是新式類裡面的寫法 self.name = name self.age = age test1(‘name‘,‘age‘) 多繼承,上面寫的都是單繼承的,python裡面還支援多繼承,多繼承就是繼承多個父類,在python3中多繼承都是廣度優先的,在python2中有點不同,經典類是深度優先,新式類是廣度優先。 class A: def say(self): print(‘A‘) class B(A): # pass def say(self): print(‘B‘) class C(A): pass # def say(self): # print(‘c‘) class D(C,B): pass s=D() s.say()
多態:python裡面是不直接支援多態的,可以通過別的方法來實現多態。通過下面的例子就可以實現一種介面,多種實現,對於下面的cry方法來說,不管你傳入的是什麼對象,只要有cry的方法,都會去調用它的cry方法,不用再一個個的去調用了
class Animal(object): ‘‘‘ 父類 ‘‘‘ def __init__(self,name): self.name = name class Dog(Animal): ‘‘‘ 狗類,有叫的方法 ‘‘‘ def cry(self): print(‘狗 [%s] 汪汪汪‘%self.name) class Cat(Animal): ‘‘‘ 貓類,有叫的方法 ‘‘‘ def cry(self): print(‘貓 [%s] 喵喵喵‘%self.name) def cry(obj): ‘‘‘ 定義一個函數,去調用傳進來的執行個體的cry方法 ‘‘‘ obj.cry() d1 = Dog(‘大黃‘)#執行個體化狗 d2 = Dog(‘小黃‘)#執行個體化狗 c1 = Cat(‘小白‘)#執行個體化貓 c2 = Cat(‘小黑‘)#執行個體化貓 cry(d1)#把對象d1傳進來 cry(d2)#把對象d2傳進來 objs = [d1,d2,c1,c2]#把上面執行個體化的對象都放到一個list裡面 for obj in objs:#迴圈統一調用 cry(obj)
私人方法,私人屬性:什麼是私人,私人就是只有在類裡面可以訪問,執行個體化之後不可以訪問和調用,有私人方法和私人屬性。私人就把變數名或者函數名前面加上"__"兩個底線,其實就是通過私人來實現封裝的。
class Dog(object): __type = ‘狗‘#私人屬性 def cry(self): self.__test()#調用私人方法 print(‘私人屬性%s‘%self.__type) print(‘狗 [%s] 汪汪汪‘%self.name) def __test(self):#私人方法 self.name = ‘test‘# d = D() d.cry()#正常可以調用 d.__type#報錯,因為是私人屬性,在外面不能訪問 d.__test()#報錯,因為是私人方法,在外面不能訪問
靜態方法和類方法:
class Stu(object): country = ‘china‘#類變數 def __init__(self,name): self.name = name @staticmethod #靜態方法,和類本身沒有什麼關係了,就相當於在類裡面定義了一個方法而已 def say(): print(‘xxx‘) @classmethod #靜態方法,和類方法不同的是,它可以使用類變數,必須要傳一個值,代表的就是這個類 def hello(cls): print(cls.country) def hi(self): #這個是執行個體方法 print(self.name) t = Stu(‘name‘) Stu.hello() Stu.say() t.hi() t.say() t.hello()
python學習筆記8--物件導向編程