python完全支持面向对象编程_Python面向对象编程
對象魔法
1.多態
多態指的是能夠同樣地對待不同類型和類的對象,既無需知道對象屬于哪個類就可調用其方法。
2.封裝
對象可能隱藏(封裝)其內部狀態。在有些語言中,這意味著對象的狀態(屬性)只能通過其方法來訪問。在Python中,所有的屬性都是公有的,但直接訪問對象的狀態時程序員應謹慎行事,因為這可能在不經意間導致狀態不一致。
3.繼承
一個類可以是一個或多個類的子類,在這種情況下,子類將繼承超類的所有方法。你可以指定多個超類,通過這樣做可組合正交(獨立且不相關)的功能。為此,一種常見的做法是使用一個核心超類以及一個或多個混合超類。
類
每個對象都屬于特定的類,并被稱為該類的實例。
例如,你在窗外看到一只鳥,這只鳥就是“鳥類”的一個實例。鳥類是一個非常通用的(抽象)的類,它有多個子類:你看到的那只鳥可能屬于子類“云雀”。你可以將“鳥類”視為由所有鳥組成的集合,而“云雀”是其一個資料集,一個類的對象為另一個類的對象的子集時,前者就是后者的子類,因此“云雀”為“鳥類”的子集,而“鳥類”為“云雀”的超類。
1.創建自定義類
1 classStudent(object):2
3 #構造方法(構造器、構造子 - constructor)
4 #調用該方法的時候不是直接使用方法的名字而是使用類的名字
5 def __init__(self, name='無名氏', age=20):#屬性
6 #給對象綁定屬性
7 self._name =name8 self._age =age9
10 #我們定義一個方法就代表對象可以接收這個消息
11 #對象的方法的第一個參數都是統一寫成self
12 #它代表了接收消息的對象 - 對象.消息(參數)
13 def study(self, course):#方法,學生的行為
14 print('%s正在學習%s' % (self._name, course))
2.屬性,函數和方法
實際上,方法和函數的區別表現在參數self上。方法(更準確地說是關聯的方法)將其第一個參數關聯到它所屬的實例,因此無需提供這個參數。無疑可以將屬性關聯到一個普通函數,但這樣就沒有特殊的self參數了。
3.隱藏
默認情況下,可以從外部訪問對象的屬性。
有些程序員認為這沒問題,但有些程序員認為這違反了封裝原則。他們認為應該對外部完全隱藏對象的狀態(即不能從外部訪問它們)。為何他們的立場如此極端?由每個對象管理自己的屬性還不夠嗎?為何要向外部隱藏屬性?畢竟,如果能直接訪問CloseObject(對象c所屬的類)的屬性name,就不需要創建方法setName了。
關鍵是其他程序員可能不知道(也不應知道)對象內部發生的情況。為避免這類問題,可以將屬性定義為私有。私有屬性不能從對象外部訪問,而只能通過存取器方法(如set_name和get_name)來訪問。
Python沒有為私有屬性提供直接的支持,而是要求程序員知道在什么情況下從外部修改屬性是安全的。畢竟,你必須在知道如何使用對象之后才能使用它。然而,通過玩點小花招,可以獲得類似于私有屬性的效果。
要讓方法或屬性成為私有的(不能從外部訪問),只需要讓其名稱以兩個下劃線打頭即可。
雖然以兩個下劃線打頭有點怪異,但這樣的方法類似于其他語言中的標準私有方法,然而,幕后的處理手法并不標準:在類定義中,對所有以兩個下劃線打頭的名稱都進行轉換,即在開頭加上一個下劃線和類名。
只要知道這種幕后處理手法,就能從類外訪問私有方法,然而不應這樣做。
總之,你無法禁止別人訪問對象的私有方法和屬性,但這種名稱修改方式發出了強烈的信號,讓他們不要這樣做。
如果你不希望名稱被修改,有想發出不要從外部修改屬性或方法的新號,可用一個下劃線打頭。這雖然只是一種約定,但也有些作用。例如,from module import *不會導入以一個下劃線打頭的名稱。
4.類的命名空間
下面的兩條語句大致等價:
def foo(x): return x *x
foo = lambda x: x * x
它們都創建一個返回參數平方的函數,并將這個函數關聯到變量foo。可以在全局(模塊)作用域內定義名稱foo,也可以在函數或方法內定義。定義類時情況亦如此:在class語句中定義的代碼都是在一個特殊的命名空間(類的命名空間)內執行的,而類的所有成員都可訪問這個命名空間。類定義其實就是要執行的代碼段,并非所有的Python程序員都知道這一點,但知道這一點很有幫助。例如,在類定義中,并非只能包含def語句。
5.指定超類
子類擴展了超類的定義。要指定超類,可在class語句中的類名后加上超類名,并將其用圓括號括起。
1 classFilter(object):2
3 def __init__(self):4 self.blocked =[]5
6 deffilter(self,sequence):7 return [x for x in sequence if x not inself.blocked]8
9
10 class SPAMFilter(Filter): #SPAMFilter是Fliter的子類
11
12 def __init__(self): #重寫超類Filter的方法init
13 self.blocked = ['SPAM']
Filter是一個過濾序列的通用類。實際上,它不會過濾掉任何東西。
Filter類的用途在于可用作其他類(如將'SPAM'從序列中過濾掉的SPAMFilter類)的基類(超類)。
請注意SPAMFilter類的定義中有兩個要點。
·以提供新定義的方式重寫了Fliter類中方法init的定義。
·直接從Filter類繼承了方法filter的定義,因此無需重新編寫其定義。
第二點說明了繼承很有用的原因:可以創建打量不同的過濾器類,它們都從Filter類派生而來,并且都使用已編寫好的方法filter。這就是懶惰的好處。
6.繼承
要確定一個類是否是另一個類的子類,可使用內置方法issubclass。
如果有一個類,并想知道它的基類,可訪問其特殊屬性__bases__。
同樣,要確定對象是否是特定類的實例,可使用isinstance。
7.接口和內省
一般而言,你無需過于深入地研究對象,而只依賴于多態來調用所需的方法。然而,如果要確定對象包含哪些方法或屬性,有一些函數可供你來完成這種工作。
8.抽象基類
使用模塊 abc可創建抽象基類。抽象基類用于指定子類必須提供哪些功能,卻不實現這些功能。
關于面向對象設計的一些思考
將相關的東西放在一起。如果一個函數操作一個全局變量,最好將它們作為一個類的屬性和方法。
不要讓對象之間過于親密。方法應只關系其所屬實例的屬性,對于其他實力的狀態,讓它們自己去管理就好了。
慎用繼承,尤其是多重繼承。繼承有時很有用,但在有些情況下可能帶來不必要的復雜性。要正確地使用多重繼承很難,要排除其中的bug更難。
保持簡單。讓方法短小緊湊。一般而言,應確保大多數方法都能在30秒內讀完并理解。對于其余的方法,盡可能將其篇幅控制在一頁或一屏內。
總結
以上是生活随笔為你收集整理的python完全支持面向对象编程_Python面向对象编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 利用python爬取_在知乎上利用Pyt
- 下一篇: 嵌入式处理器 cisc risc_RIS