Python要麼是面向過程要麼是面向對象。python
概念及優缺點:git
面向過程的程序設計的核心是過程,過程即解決問題的步驟,面向過程的設計就比如精心設計好一條流水線,考慮周全何時處理什麼東西。編程
優勢是:極大的下降了程序的複雜度ide
缺點是:一套流水線或者流程就是用來解決一個問題,生產汽水的流水線沒法生產汽車,即使是能,也得是大改,改一個組件,牽一髮而動全身。函數
應用場景:一旦完成基本不多改變的場景,著名的例子有Linux內核,git,以及Apache HTTP Server等。spa
面向對象的程序設計的核心是對象,要理解對象爲什麼物,必須把本身當成上帝,上帝眼裏世間存在的萬物皆爲對象,不存在的也能夠創造出來。面向對象的程序設計比如如來設計西遊記,如來要解決的問題是把經書傳給東土大唐,如來想了想解決這個問題須要四我的:唐僧,沙和尚,豬八戒,孫悟空,每一個人都有各自的特徵和技能(這就是對象的概念,特徵和技能分別對應對象的數據屬性和方法屬性),然而這並很差玩,因而如來又安排了一羣妖魔鬼怪,爲了防止師徒四人在取經路上被搞死,又安排了一羣神仙保駕護航,這些都是對象。而後取經開始,師徒四人與妖魔鬼怪神仙交互着直到最後取得真經。如來根本不會管師徒四人按照什麼流程去取。設計
面向對象的程序設計3d
優勢是:解決了程序的擴展性。對某一個對象單獨修改,會馬上反映到整個體系中,如對遊戲中一我的物參數的特徵和技能修改都很容易。指針
缺點:可控性差,沒法向面向過程的程序設計流水線式的能夠很精準的預測問題的處理流程與結果,面向對象的程序一旦開始就由對象之間的交互解決問題,即使是上帝也沒法預測最終結果。因而咱們常常看到一個遊戲人某一參數的修改極有可能致使陰霸的技能出現,一刀砍死3我的,這個遊戲就失去平衡。code
應用場景:需求常常變化的軟件,通常需求的變化都集中在用戶層,互聯網應用,企業內部軟件,遊戲等都是面向對象的程序設計大顯身手的好地方
面向對象的程序設計並非所有。對於一個軟件質量來講,面向對象的程序設計只是用來解決擴展性。
python中一切皆爲對象,且python3統一了類與類型的概念,類型就是類,因此,無論你信不信,你已經使用了很長時間的類了
1 >>> dict #類型dict就是類dict 2 <class 'dict'> 3 >>> d=dict(name='luchuan') #實例化 4 >>> d.pop('name') #向d發一條消息,執行d的方法pop 5 'luchuan' 6 >>>
基於面向對象設計一個款遊戲:英雄聯盟,每一個玩家選一個英雄,每一個英雄都有本身的特徵和和技能,特徵即數據屬性,技能即方法屬性,特徵與技能的結合體就一個對象。
從一組對象中提取類似的部分就是類,類也是特徵與技能的結合體,特徵即數據而且是全部對象共享的數據,技能即函數屬性而且是全部對象共享的函數屬性。
注:現實生活中,先有了原形人物,纔有了類。
python編程中,是先有了類,再有了對象,例如dict。
先定義類,由類產生具體得對象。類是提取了共同的特徵和技能組成得。什麼等於什麼,這是特徵。技能就是功能。
類有兩種做用:引用名字和實例化,引用名字包括(類名.變量名,類名.函數名)
對象/實例只有一種做用:引用名字包括(實例名.類的變量,實例名.綁定方法,實例名.實例本身的變量名)
3.1 初識類
在python中聲明函數與聲明類很類似
聲明函數
1 def functionName(args): 2 '函數文檔字符串' 3 函數體
聲明類
1 ''' 2 class 類名: 3 '類的文檔字符串' 4 類體 5 ''' 6 7 #咱們建立一個類 8 class Data: 9 pass
大前提: 1.只有在python2中才分新式類和經典類,python3中統一都是新式類 2.新式類和經典類聲明的最大不一樣在於,全部新式類必須繼承至少一個父類 3.全部類甭管是否顯式聲明父類,都有一個默認繼承object父類(講繼承時會講,先記住) 在python2中的區分 經典類: class 類名: pass 經典類: class 類名(父類): pass 在python3中,上述兩種定義方式全都是新式類 經典類與新式類
在本節開頭介紹得出結論,類是數據與函數的結合,兩者稱爲類的屬性
class Garen: #定義英雄蓋倫的類,不一樣的玩家能夠用它實例出本身英雄; camp='Demacia' #全部玩家的英雄(蓋倫)的陣營都是Demacia; def attack(self,enemy): #普通攻擊技能,enemy是敵人; enemy.life_value-=self.aggressivity #根據本身的攻擊力,攻擊敵人就減掉敵人的生命值。
3.2.1 類有兩種做用:引用名字和實例化
引用名字(類名.屬性),也能夠理解成引用類的特徵(類的變量)和技能(類的函數)
>>> Garen.camp #引用類的數據屬性,該屬性與全部對象/實例共享 'Demacia' >>> Garen.attack #引用類的函數屬性,該屬性也共享 <function Garen.attack at 0x101356510> >>> Garen.name='Garen' #增長屬性 >>> del Garen.name #刪除屬性
3.2.2 實例化(__init__與self)
x=int(10) #實例化 print(x) obj=Garen() #實例化 print(obj)
類名加括號就是實例化,會自動觸發__init__函數的運行,能夠用它來爲每一個實例定製本身的特徵
class Garen: #定義英雄蓋倫的類,不一樣的玩家能夠用它實例出本身英雄; camp='Demacia' #全部玩家的英雄(蓋倫)的陣營都是Demacia; def __init__(self,nickname,aggressivity=58,life_value=455): #英雄的初始攻擊力58...; self.nickname=nickname #爲本身的蓋倫起個別名; self.aggressivity=aggressivity #英雄都有本身的攻擊力; self.life_value=life_value #英雄都有本身的生命值; def attack(self,enemy): #普通攻擊技能,enemy是敵人; enemy.life_value-=self.aggressivity #根據本身的攻擊力,攻擊敵人就減掉敵人的生命值。
實例化:類名+括號
>>> g1=Garen('草叢倫') #就是在執行Garen.__init__(g1,'草叢倫'),而後執行__init__內的代碼g1.nickname=‘草叢倫’等
self的做用是在實例化時自動將對象/實例自己傳給__init__的第一個參數,self能夠是任意名字,可是瞎幾把寫別人就看不懂了。
這種自動傳遞的機制還體如今g1.attack的調用上,後續會介紹。
一:咱們定義的類的屬性到底存到哪裏了?有兩種方式查看 dir(類名):查出的是一個名字列表 類名.__dict__:查出的是一個字典,key爲屬性名,value爲屬性值 二:特殊的類屬性 類名.__name__# 類的名字(字符串) 類名.__doc__# 類的文檔字符串 類名.__base__# 類的第一個父類(在講繼承時會講) 類名.__bases__# 類全部父類構成的元組(在講繼承時會講) 類名.__dict__# 類的字典屬性 類名.__module__# 類定義所在的模塊 類名.__class__# 實例對應的類(僅新式類中) 類屬性的補充
3.3 對象/實例只有一種做用:屬性引用
#對象/實例自己其實只有數據屬性 >>> g1.nickname '草叢倫' >>> g1.aggressivity >>> g1.life_value ''' 查看實例屬性 一樣是dir和內置__dict__兩種方式 特殊實例屬性 __class__ __dict__ .... '''
對象/實例自己只有數據屬性,可是python的class機制會將類的函數綁定到對象上,稱爲對象的方法,或者叫綁定方法。
綁定方法的核心在於‘綁定’,惟一綁定一個肯定的對象。
>>> g1.attack #對象的綁定方法 <bound method Garen.attack of <__main__.Garen object at 0x101348dd8>> >>> Garen.attack #對象的綁定方法attack本質就是調用類的函數attack的功能,兩者是一種綁定關係 <function Garen.attack at 0x101356620>
對象的綁定方法的特別之處在於:obj.func()會把obj傳給func的第一個參數。
咱們能夠仿照garen類再建立一個Riven類
class Riven: camp='Noxus' #全部玩家的英雄(銳雯)的陣營都是Noxus; def __init__(self,nickname,aggressivity=54,life_value=414): #英雄的初始攻擊力54; self.nickname=nickname #爲本身的銳雯起個別名; self.aggressivity=aggressivity #英雄都有本身的攻擊力; self.life_value=life_value #英雄都有本身的生命值; def attack(self,enemy): #普通攻擊技能,enemy是敵人; enemy.life_value-=self.aggressivity #根據本身的攻擊力,攻擊敵人就減掉敵人的生命值。
實例出一個Riven來
>>> r1=Riven('銳雯雯')
交互:銳雯雯攻擊草叢倫,反之同樣
>>> g1.life_value 455 >>> r1.attack(g1) >>> g1.life_value 401
建立一個類就會建立一個類的名稱空間,用來存儲類中定義的全部名字,這些名字稱爲類的屬性
而類有兩種屬性:數據屬性和函數屬性
其中類的數據屬性是共享給全部對象的
>>> id(r1.camp) #本質就是在引用類的camp屬性,兩者id同樣 4315241024 >>> id(Riven.camp) 4315241024
而類的函數屬性是綁定到全部對象的:
>>> id(r1.attack) >>> id(Riven.attack) ''' r1.attack就是在執行Riven.attack的功能,python的class機制會將Riven的函數屬性attack綁定給r1,r1至關於拿到了一個指針,指向Riven類的attack功能 除此以外r1.attack()會將r1傳給attack的第一個參數 '''
g1=Garen('草叢倫') print(g1.__dict__) g1.__dict__["x"]=1 #對象支持直接賦值 print(g1.__dict__) Garen.__dict__["x"]=1 # Garen不支持直接賦值 print(Garen.__dict__)
建立一個對象/實例就會建立一個對象/實例的名稱空間,存放對象/實例的名字,稱爲對象/實例的屬性
在obj.name會先從obj本身的名稱空間裏找name,找不到則去類中找,類也找不到就找父類...最後都找不到就拋出異常