面向對象編程(1)
楔子
你現在是一家遊戲公司的開發人員,現在需要你開發一款叫做<人狗大戰>的遊戲,你就思考呀,人狗作戰,那至少需要2個角色,一個是人, 一個是狗,且人和狗都有不同的技能,比如人拿棍打狗, 狗可以咬人,怎麽描述這種不同的角色和他們的功能呢?
你搜羅了自己掌握的所有技能,寫出了下面的代碼來描述這兩個角色
def person(name,age,sex,job): data = { ‘name‘:name, ‘age‘:age, ‘sex‘:sex, ‘job‘:job }return data def dog(name,dog_type): data = { ‘name‘:name, ‘type‘:dog_type } return data
上面兩個方法相當於造了兩個模子,遊戲裏的每個人和每條狗都擁有相同裏的屬性。遊戲開始,你根據一個人或一只狗傳入的具體信息來塑造一個具體的人或者狗,怎麽生成呢?
d1 = dog("李磊","京巴") p1 = person("嚴帥",36,"F","運維") p2 = person("egon",27,"F","Teacher")
兩個角色對象生成了,狗和人還有不同的功能呀,狗會旺旺叫,人會散步,對不對? 怎麽實現呢,。。想到了, 可以每個功能再寫一個函數,想執行哪個功能,直接調用就可以了,對不?
def bark(d): print("dog %s:wang.wang..wang..."%d[‘name‘]) def walk(p): print("person %s is walking..." %p[‘name‘])
walk(p1) bark(d1)
上面的功能實現的簡直是完美!
但是仔細玩耍一會,你就不小心幹了下面這件事
p1 = person("嚴帥",36,"F","運維") bark(p1) #把人的對象傳給了狗的方法
事實 上,從你寫的代碼上來看,這並沒出錯。很顯然,人是不能調用狗的功能的,但在你的程序例沒有做限制,如何在代碼級別實現這個限制呢?
def person(name,age,sex,job): def walk(p): print("person %s is walking..." % p[‘name‘]) data = { ‘name‘:name, ‘age‘:age, ‘sex‘:sex, ‘job‘:job, ‘walk‘:walk } return data def dog(name,dog_type): def bark(d): print("dog %s:wang.wang..wang..."%d[‘name‘]) data = { ‘name‘:name, ‘type‘:dog_type, ‘bark‘:bark } return data d1 = dog("李磊","京巴") p1 = person("嚴帥",36,"F","運維") p2 = person("egon",27,"F","Teacher") d1[‘bark‘](p1) #把人傳給了狗的方法
你是如此的機智,這樣就實現了限制人只能用人自己的功能啦。
剛剛你用的這種編程思想其實就是簡單的面向對象編程,我們創造了兩個模子表示遊戲裏所有的人和狗之後,剩下的狗叫或者人走對於這兩個模子來說就不重要了。具體人he狗之間的交互就等著你去使用了。假如你和狗打起來了,這時候你是走路還是拿棍子打狗就由你自己決定了。那你的每一個決定可能都影響著你這場遊戲的輸贏。這也是不確定的。和我們之前寫代碼按部就班的走,最終都會實現我們要完成的事情不太一樣了。
盡管如此,我們也只完成了這個遊戲非常小的一部分。還有很多功能都沒有實現。
剛才你只是阻止了兩個完全不同的角色 之前的功能混用, 但有沒有可能 ,同一個種角色,但有些屬性是不同的呢? 比如 ,大家都打過cs吧,cs裏有警察和恐怖份子,但因為都是人, 所以你寫一個角色叫 person(), 警察和恐怖份子都可以互相射擊,但警察不可以殺人質,恐怖分子可以,這怎麽實現呢? 你想了說想,說,簡單,只需要在殺人質的功能裏加個判斷,如果是警察,就不讓殺不就ok了麽。 沒錯, 這雖然 解決了殺人質的問題,但其實你會發現,警察和恐怖分子的區別還有很多,同時又有很多共性,如果 在每個區別處都 單獨做判斷,那得累死。
你想了想說, 那就直接寫2個角色吧, 反正 這麽多區別, 我的哥, 不能寫兩個角色呀,因為他們還有很多共性 , 寫兩個不同的角色,就代表 相同的功能 也要重寫了,是不是我的哥? 。。。
好了, 話題就給你點到這, 再多說你的智商也理解不了了!
面向過程 VS 面向對象
面向過程的程序設計的核心是過程(流水線式思維),過程即解決問題的步驟,面向過程的設計就好比精心設計好一條流水線,考慮周全什麽時候處理什麽東西。
優點是:極大的降低了寫程序的復雜度,只需要順著要執行的步驟,堆疊代碼即可。
缺點是:一套流水線或者流程就是用來解決一個問題,代碼牽一發而動全身。
應用場景:一旦完成基本很少改變的場景,著名的例子有Linux內核,git,以及Apache HTTP Server等。
面向對象的程序設計的核心是對象(上帝式思維),要理解對象為何物,必須把自己當成上帝,上帝眼裏世間存在的萬物皆為對象,不存在的也可以創造出來。面向對象的程序設計好比如來設計西遊記,如來要解決的問題是把經書傳給東土大唐,如來想了想解決這個問題需要四個人:唐僧,沙和尚,豬八戒,孫悟空,每個人都有各自的特征和技能(這就是對象的概念,特征和技能分別對應對象的屬性和方法),然而這並不好玩,於是如來又安排了一群妖魔鬼怪,為了防止師徒四人在取經路上被搞死,又安排了一群神仙保駕護航,這些都是對象。然後取經開始,師徒四人與妖魔鬼怪神仙互相纏鬥著直到最後取得真經。如來根本不會管師徒四人按照什麽流程去取。
面向對象的程序設計的
優點是:解決了程序的擴展性。對某一個對象單獨修改,會立刻反映到整個體系中,如對遊戲中一個人物參數的特征和技能修改都很容易。
缺點:可控性差,無法向面向過程的程序設計流水線式的可以很精準的預測問題的處理流程與結果,面向對象的程序一旦開始就由對象之間的交互解決問題,即便是上帝也無法預測最終結果。
應用場景:需求經常變化的軟件,一般需求的變化都集中在用戶層,互聯網應用,企業內部軟件,遊戲等都是面向對象的程序設計大顯身手的好地方。
在python 中面向對象的程序設計並不是全部。
面向對象編程可以使程序的維護和擴展變得更簡單,並且可以大大提高程序開發效率 ,另外,基於面向對象的程序可以使它人更加容易理解你的代碼邏輯,從而使團隊開發變得更從容。
了解一些名詞:類、對象、實例、實例化
類:具有相同特征的一類事物(人、狗、老虎)
對象/實例:具體的某一個事物(隔壁阿花、樓下旺財)
實例化:類——>對象的過程(這在生活中表現的不明顯,我們在後面再慢慢解釋)
類與對象語法實現
聲明類
def functionName(args): ‘函數文檔字符串‘ 函數體 ‘‘‘ class 類名: ‘類的文檔字符串‘ 類體 ‘‘‘ #我們創建一個類 class Data: pass class Person: #定義一個人類 role = ‘person‘ #人的角色屬性都是人 def walk(self): #人都可以走路,也就是有一個走路方法,也叫動態屬性 print("person is walking...")
類實例化
實例化的過程就是類——>對象的過程
原本我們只有一個Person類,在這個過程中,產生了一個egg對象,有自己具體的名字、攻擊力和生命值。
# 語法:對象名 = 類名(參數) egg = Person(‘egon‘) # 類名()就等於在執行Person.__init__() # 執行完__init__()就會返回一個對象。這個對象類似一個字典,存著屬於這個人本身的一些屬性和方法。
查看屬性和調用方法:
print(egg.name) #查看屬性直接 對象名.屬性名 print(egg.walk()) #調用方法,對象名.方法名()
註意:self:在實例化時自動將對象/實例本身傳給__init__的第一個參數,你也可以給他起個別的名字,但是正常人都不會這麽做。因為你瞎改別人就不認識
面向對象編程(1)