介紹模塊和類怎麼互相轉換,不談面向對象的繼承 封裝 多態等特色。php
一個person_module模塊,有人的基本屬性和功能。html
person_module.py以下java
# coding=utf8 name = '小明' eye_color = 'blue' age = 10 def get_eye_color(): return name + '的眼睛顏色是: ' + eye_color def show_age(): print name + '的年齡是: ' + str(age) def grow(): print name + ' 增加一歲了' globals()['age'] += 1 ##這裏要注意必定要這樣寫活着聲明age是全局的,不然會出錯 print globals()['age'] show_age() if __name__ == "__main__": print get_eye_color() show_age() grow()
如今假如這個模塊是別人寫的,咱們拿來用,如今咱們要把名字換成小紅,眼睛顏色換成黑色,年齡換成15歲,成長函數,一次增長兩歲python
那咱們就須要修改別人的源碼文件了,可能改着改着改錯了,不知道怎麼復原了。es6
那就import這個模塊吧。web
xiaohong.py編程
# coding=utf8 import person_module as p from person_module import * p.name = '小紅' p.age = 14 p.eye_color = 'black' def grow(): print p.name + ' 增加一歲了' p.age += 2 print p.age show_age() p.grow = grow print p.get_eye_color() show_age() p.grow() # 直接grow()也能夠
能夠看到屬性被替換了,連增加函數也被替換了,一次增加兩歲。設計模式
這就是給模塊打猴子補丁了,這樣寫很彆扭的實現了模塊繼承,相似於類繼承。函數
但願把這個模塊轉換成類,oop編程。工具
模塊和類的轉換規則是:
一、模塊級降爲類
二、全局變量改爲實例屬性,全局的不會被改變的變量相似於那種const的,能夠寫成類屬性(減小點內存存儲能夠)。
三、而後把函數改爲方法。方法是類裏面的,函數是模塊裏面的。
看person.py
# coding=utf8 class Person(object): def __init__(self, name, age,eye_color): self.name = name self.eye_color = eye_color self.age = age def get_eye_color(self): return self.name + '的眼睛顏色是: ' + self.eye_color def show_age(self): print self.name + '的年齡是: ' + str(self.age) def grow(self): print self.name + ' 增加一歲了' self.age += 1 self.show_age() if __name__ == "__main__": xiaohong = Person('小紅', 14, 'black') print xiaohong.get_eye_color() xiaohong.show_age() xiaohong.grow()
這樣作了以後,統一經過self就能訪問age name了,改變age也不須要蛋疼的聲明一下age是全局的那個了。
就這樣三個步驟,就能把面向過程的模塊改爲面向對象了。
最主要是前面那種導入模塊的方法,打補丁很麻煩,那例子還只是實現小紅,若是要實現小黃、小花,那就複雜了。若是使用oop,類的多個實例就天然多了,也簡單直觀。
若是要改變grow方法,繼承一下就好了,改爲這樣
大部分入門都是第一種寫法,畢竟py編程太自由了,能夠一條條從上往下指令平鋪,也能夠抽成函數,也能夠oop。用py會長期造成了懶惰的寫法用前面第一種,但複用性真的比oop差不少,整體看起來也low一些。好比多個過程須要共享中間狀態時,單純的使用函數會寫得很糟糕,這時候就應當使用類,不然要麼搞全局變量要麼頻繁的return頻繁的傳參,爲何反對模塊編程,就是由於模塊難以初始化賦值,模塊的多實例難以搞,類能很好解決。非oop一些設計模式很難用上。也有人堅定說他不須要oop,說不須要那是沒認真對比過,或者壓根不瞭解,只是死記硬背類的 繼承 封裝多態這幾個詞語,並無實踐對比過。還有的說python裏面一切皆是對象,因此他寫的就是oop,沒錯,那樣僅限於有int 類 str類 字典類 或者導入了三方庫後有了Request類 Response類,selenim的webdriver的Chrome類 Firefox類,僅限於此啊,沒有本身的類,python一切皆對象(在py裏面隨便寫個 a = 5,a就能夠說是int類的一個實例了,py是面向對象的極致,甚至比java還極致,java裏面的int a = 5,a是基本數據類型,要用到一些必要的方法支持還的把a轉成Interger類的對象,php裏面的字符串操做是由函數完成的,php的小寫字符串轉大寫是 strtoupper("Hello WORLD!"),py的小寫轉大寫是「Hello WORLD!」.uper(),object.func()和func(object)就是op和oo的區別。除了py裏面的例如__len__用,len(str1)來獲取長度,但這種是經過反射完成,也能夠用str.__len__(),len(str)形式上看起來不那麼oo。)雖然py一切皆對象,py是最極致的面向對象,但這不表明隨便寫就是oop編程了。三方庫爲何調用的那麼爽,那是人家oop了,人家三方庫全寫函數,調用起來就知道什麼叫痛苦了,都不知道應該調用哪些函數來處理那個對象了。這都什麼年代了,還對oop持懷疑和反對態度。php py js es6都是在慢慢的後來加入類的概念,難道發明語言的人會比咱們差嗎。
必須對py的oop很是熟悉,才能開始學習java。否則的是確定看不懂java。
一個模塊內能夠多個類,類能夠把模塊分割裂更小的模塊組織單元。oo大量實例化時候須要佔用更多的內存,性能是比op差。若是擔憂oo性能比op差,那同樣能夠適當地寫類裏面的靜態方法或者類方法,無需實例化,經常使用的工具方法不要全寫成實例方法,幹個啥都要實例化,該用靜態就要用靜態。
這是一些體會,po和oo每次寫時候順便腦補一下,另外一種大概是怎麼樣的。全局變量太多,多個函數操做一個東西,就能夠想下oop,oo能消滅全局,平鋪式的代碼適合簡單腳本,或者快速驗證和測試或者頂層腳本,但若是是做爲被導入模塊,再用這種寫法,模塊裏面大量寫非final類型的全局變量是很腦殘的低級入門寫法。模塊級的po是拿個源碼腳本,處處去修改一些變量的值,例如age name什麼的。oo是對數據和方法的封裝,op是函數和傳參分離在兩個地方。
以上爲簡單例子,oop的進階是設計模式。
若是不是按照這種寫人的方式,全局變量加函數的面向過程寫法,而是徹底的沒有全局變量一步步return和傳參的,執行三步走那就是隻有class外殼的類,仍然是一個面向過程的類,須要再加一步。