Python面向對象編程——簡介

Python面向對象編程——簡介

編程範式

編程是程序員用特定的語法+數據結構+算法組成的代碼來告訴計算機如何執行任務的過程 。python

一個程序是程序員爲了獲得一個任務結果而編寫的一組指令的集合,正所謂條條大路通羅馬,實現一個任務的方式有不少種不一樣的方式, 對這些不一樣的編程方式的特色進行概括總結得出來的編程方式類別,即爲編程範式。 不一樣的編程範式本質上表明對各類類型的任務採起的不一樣的解決問題的思路, 大多數語言只支持一種編程範式,固然也有些語言能夠同時支持多種編程範式。 兩種最重要的編程範式分別是面向過程編程和麪向對象編程。程序員

1、面向過程編程(Procedural Programming)

Procedural programming uses a list of instructions to tell the computer what to do step-by-step.算法

面向過程編程依賴 - 你猜到了- procedures,一個procedure包含一組要被進行計算的步驟, 面向過程又被稱爲top-down languages, 就是程序從上到下一步步執行,一步步從上到下,從頭至尾的解決問題 。基本設計思路就是程序一開始是要着手解決一個大的問題,而後把一個大問題分解成不少個小問題或子過程,這些子過程再執行的過程再繼續分解直到小問題足夠簡單到能夠在一個小步驟範圍內解決。編程

舉個典型的面向過程的例子, 寫一個數據遠程備份程序, 分三步,本地數據打包,上傳至雲服務器,測試備份文件可用性。服務器

def cloud_upload(file):

        print("\nconnecting cloud storage center...")
        print("cloud storage connected.")
        print("upload file...xxx..to cloud...", file)
        print('close connection.....')


def data_backup(folder):
    print("找到要備份的目錄...", folder)
    print("將備份文件打包,移至相應目錄...")
    return '/tmp/backup20181103.zip'

def data_backup_test():

    print("\n從另一臺機器將備份文件從遠程cloud center下載,看文件是否無損")


def main():
    zip_file = data_backup("c:\\users\\alex\歐美100G高清無碼")

    cloud_upload(zip_file)

    data_backup_test()


if __name__ == '__main__':
    main()

這個變量,那這個子過程你也要修改,假如又有一個其它子程序依賴這個子過程 , 那就會發生一連串的影響,隨着程序愈來愈大, 這種編程方式的維護難度會愈來愈高。數據結構

test = 1

def cloud_upload(file):

    if test == 1:
        print("\nconnecting cloud storage center...")
        print("cloud storage connected.")
        print("upload file...xxx..to cloud...", file)
        print('close connection.....')
        return True
    else:
        print("不備份")
        return False

def data_backup(folder):
    print("找到要備份的目錄...", folder)
    print("將備份文件打包,移至相應目錄...")
    return '/tmp/backup20181103.zip'

def data_backup_test(upload_res):
    if upload_res == 1:
        print("\n從另一臺機器將備份文件從遠程cloud center下載,看文件是否無損")
    else:
        print("upload error,不備份")

def main():
    zip_file = data_backup("c:\\users\\alex\歐美100G高清無碼")

    res = cloud_upload(zip_file)

    data_backup_test(res)


if __name__ == '__main__':
    main()

因此咱們通常認爲, 若是你只是寫一些簡單的腳本,去作一些一次性任務,用面向過程的方式是極好的,但若是你要處理的任務是複雜的,且須要不斷迭代和維護 的, 那仍是用面向對象最方便了。框架

2、面向對象編程(Object Oriented Programing)

直接解釋,你必然會蒙逼,因此先講個引子。函數

你如今是一家遊戲公司的開發人員,如今須要你開發一款叫作 <人狗大戰> 的遊戲,你就思考呀,人狗做戰,那至少須要2個角色,一個是人, 一個是狗,且人和狗都有不一樣的技能,好比人拿棍打狗, 狗能夠咬人,怎麼描述這種不一樣的角色和他們的功能呢? 學習

你搜羅了本身掌握的全部技能,寫出了下面的代碼來描述這兩個角色:測試

person = {
    'name':'Alex',
    'attack': 100, #殺傷力
    'life_value':1000
}


dog = {
    'name':'Peiqi',
    'attack': 200, #殺傷力
    'life_value':800
}

一個字典表示一個角色實體,但若是有多條狗和多我的一塊兒打呢?那就得寫多個字典。

person = {
    'name':'Alex',
    'attack': 100, #殺傷力
    'life_value':1000
}
person2 = {
    'name':'Black Girl',
    'attack': 100, #殺傷力
    'life_value':600
}


dog = {
    'name':'Peiqi',
    'attack': 200, #殺傷力
    'life_value':800
}

這樣是有問題的,由於若是你字典裏的值不當心定義錯了,把attack寫成了了atteck的話,那整個程序就有問題了。so 你很快想出了改進方案,把字典放進函數

def person(name,attack,life_value):
    data = {
        'name':name,
        'attack':attack,
        'life_value':life_value,
    }
    return data


def dog(name, attack, life_value):
    data = {
        'name': name,
        'attack': attack,
        'life_value': life_value,
    }
    return data
  
alex = person("Alex",100,1000)
rain = person("Black girl",80,700)

d = dog("PeiQi",200,800)

好,如今角色定義好了,還差每一個角色的功能,人打狗,狗咬人的功能要定義出來

....

def attack(p,d):
    """人打狗功能"""

    d['life_value'] -= p['attack'] #被打了,要掉血
    print("人[%s] 打了 狗[%s]。。。,[%s]的生命值還有[%s]" % (p['name'], d['name'],d['name'],d['life_value']))

def bite(d,p):
    """狗咬人功能"""
    p['life_value'] -= d['attack']
    print("狗[%s] 咬了 人[%s]。。。,[%s]的生命值還有[%s]" % (d['name'], p['name'],p['name'],p['life_value']))

alex = person("Alex",100,1000)
black_girl = person("Black girl",80,700)

d = dog("PeiQi",200,800)

attack(alex,d)
bite(d,black_girl)

如今,就能夠開心的玩耍啦。。。

但玩着玩着, 你不當心調用錯了,

bite(alex,black_girl) #你調用咬人功能時,把alex當狗傳進去了,結果就變成了以下
人[Alex] 打了 狗[PeiQi]。。。,[PeiQi]的生命值還有[700]

狗[PeiQi] 咬了 人[Black girl]。。。,[Black girl]的生命值還有[500]

狗[Alex] 咬了 人[Black girl]。。。,[Black girl]的生命值還有[400]

你讓我咬black_girl一口我不介意,但以狗的身份,我是反對的,因此這明顯是個bug,bite()功能是狗專屬的,不該該容許人調用,這可怎麼辦呢?

哈,想了一會,你又搞定了。

def person(name,attack_val,life_value):

    def attack( d):
        """人打狗功能"""

        d['life_value'] -= attack_val  # 被打了,要掉血
        print("人[%s] 打了 狗[%s]。。。,[%s]的生命值還有[%s]" % (name, d['name'], d['name'], d['life_value']))

    data = {
        'name':name,
        'attack_val':attack_val,
        'life_value':life_value,
        'attack':attack
    }
    return data


def dog(name, attack_val, life_value):

    def bite(p):
        """狗咬人功能"""
        p['life_value'] -= attack_val
        print("狗[%s] 咬了 人[%s]。。。,[%s]的生命值還有[%s]" % (name, p['name'], p['name'], p['life_value']))

    data = {
        'name': name,
        'attack_val': attack_val,
        'life_value': life_value,
        'bite':bite
    }
    return data

  
  
alex = person("Alex",100,1000)
black_girl = person("Black girl",80,700)

d = dog("PeiQi",200,800)

alex['attack'](d)
d['bite'](black_girl)

你是如此的機智,這樣就實現了限制人只能用人本身的功能啦。

但,個人哥,不要高興太早,剛纔你只是阻止了兩個徹底 不一樣的角色 之間的功能混用, 但有沒有可能 ,同一個種角色,但有些屬性是不一樣的呢? 好比 ,如今遊戲升級了,不只能夠打狗,還能夠生孩子,但男人不能生呀,只能女的生,怎麼辦呢?你想了想說,簡單呀, 在person函數裏包一個子函數叫get_birth(),

def get_birth(person_data):
    if person_data['sex'] == 'female':
        print("%s生孩子 啦..."% person_data['name'] )
    else:
        print("你是男的生個毛線.")

沒錯, 這雖然解決了只能女人生孩子的問題,但其實隨着遊戲功能愈來愈多,你會發出男女之間的區別也愈來愈多 ,但又同時有不少共性,若是 在每一個區別處都 單獨作判斷,那得累死。

你想了想說, 那就直接寫2個角色吧, 反正 這麼多區別, 個人哥, 不能寫兩個角色呀,由於他們還有不少共性 , 寫兩個不一樣的角色,就表明 相同的功能 也要重寫了,是否是個人哥? 。。。 沒話說了吧?哈哈, 就是要逼你到絕路上。

上面的問題經過面向對象編程可輕鬆解決!

什麼是面向對象編程?

OOP(Object Oriented Programing)編程是利用「類」和「對象」來建立各類模型來實現對真實世界的描述。

上面的描述你一定是懵逼的,用白話解釋面向對象與面向過程的區別就是:

面向過程 = 我的視角

我要去作大保健,我只需考慮,我有沒有錢,去哪家店,怎麼去,作什麼價位的就能夠,你的每一步都要經過程序定義出來,寫死了,在這個程序裏,你只被設定了去作大保健的功能,你說中途我想去個ktv,那可能會致使整個程序的邏輯都得更改。 用面向過程的方式寫代碼,那你care的就是整個事情的執行過程

面向對象 = 上帝視角

若是你是上帝,你如今要創世紀,把這麼多人、動物、山河造出來,上帝光靠本身幹,一個一個的造人,多累呀,讓你幹這個活,你確定是先造模子,一個男人模子,一個女人模子,剩下的就一個個複製就行啦。這個模子的做用是什麼?模子定義了人這個物種所具有的全部特徵(或者說,咱們把具有這些特徵的個體歸爲人類)。

這個世界上全部的東西都是你定義的,你須要用最高效的方式去造世界,最高效的方式就是,先把世界按物種、樣貌、有無生命等各類維度分類,而後給每類東西建模型,再讓其在不脫離你基本橫型定義的框架下,自我繁衍(世界要多姿多彩,因此即便是同一物種,也要有些不同)

爲何要用面向對象?

一、使程序更加容易擴展和易更改,使開發效率變的更高。

二、基於面向對象的程序可使它人更加容易理解你的代碼邏輯,從而使團隊開發變得更從容。

3、面向對象介紹

學習面向對象過程當中會遇到一些名詞,咱們先解釋下:

名詞解釋

:一個類便是一類擁有相同屬性的對象的抽象、藍圖、原型、模板。在類中定義了這些對象都具有的屬性(variables(data))、共同的方法。

屬性:人類包含不少特徵,這些特徵用程序來描述的話,叫作屬性,好比年齡、身高、性別、姓名等都叫作屬性,一個類中,能夠有多個屬性。

方法:人類不止有身高、年齡、性別這些屬性,還能作不少事情,好比說話、走路、吃飯等,相比較於屬性是名詞,說話、走路是動詞,這些動詞用程序來描述就叫作方法。

實例(對象):一個對象便是一個類實例化後的實例,一類必須通過實例化以後纔可在程序中調用,一個類能夠實例化多個對象,每一個對象亦能夠有不一樣的屬性,就像人類是指全部人,每一個人是指具體的對象,人與人之間有共性,亦有不一樣。

實例化:把一個類轉變爲一個對象的過程就叫實例化。

面向對象的3大特性

Encapsulation 封裝

在類中對數據的賦值、內部調用對外部用戶是透明的,這使類變成了一個膠囊或容器,裏面包含着類的數據和方法。

Inheritance 繼承

一個類能夠派生出子類,在這個父類裏定義的屬性、方法自動被子類繼承。

Polymorphism 多態

多態是面向對象的重要特性,簡單點說:「一個接口,多種實現」,指一個基類中派生出了不一樣的子類,且每一個子類在繼承了一樣的方法名的同時又對父類的方法作了不一樣的實現,這就是同一種事物表現出的多種形態。

編程其實就是一個將具體世界進行抽象化的過程,多態就是抽象化的一種體現,把一系列具體事物的共同點抽象出來, 再經過這個抽象的事物, 與不一樣的具體事物進行對話。

對不一樣類的對象發出相同的消息將會有不一樣的行爲。好比,你的老闆讓全部員工在九點鐘開始工做, 他只要在九點鐘的時候說:「開始工做」便可,而不須要對銷售人員說:「開始銷售工做」,對技術人員說:「開始技術工做」, 由於「員工」是一個抽象的事物, 只要是員工就能夠開始工做,他知道這一點就好了。至於每一個員工,固然會各司其職,作各自的工做。

多態容許將子類的對象看成父類的對象使用,某父類型的引用指向其子類型的對象,調用的方法是該子類型的方法。這裏引用和調用方法的代碼編譯前就已經決定了,而引用所指向的對象能夠在運行期間動態綁定。

相關文章
相關標籤/搜索