第 1/1 Python語(yǔ)言的誕生Python的作者,Guido von Rossum(吉多·范·羅蘇姆,中國(guó)Python程序員都叫他 龜叔),荷蘭人。1982年,龜叔從阿姆斯特丹大學(xué)獲得了數(shù)學(xué)和計(jì)算機(jī)碩士學(xué)位。然而,盡管他算得上是一位數(shù)學(xué)家,但他更加享受計(jì)算機(jī)帶來(lái)的樂(lè)趣。用他的話說(shuō),雖然擁有數(shù)學(xué)和計(jì)算機(jī)雙料資質(zhì),他總趨向于做計(jì)算機(jī)相關(guān)的工作,并熱衷于做任何和編程相關(guān)的事情。 1989年,為了打發(fā)圣誕節(jié)假期,龜叔開(kāi)始寫(xiě)Python語(yǔ)言的編譯器。Python這個(gè)名字,來(lái)自龜叔所摯愛(ài)的電視劇Monty Python's Flying Circus。他希望這個(gè)新的叫做Python的語(yǔ)言,能符合他的理想:創(chuàng)造一種C和shell之間,功能全面,易學(xué)易用,可拓展的語(yǔ)言。龜叔作為一個(gè)語(yǔ)言設(shè)計(jì)愛(ài)好者,已經(jīng)有過(guò)設(shè)計(jì)語(yǔ)言的嘗試。這一次,也不過(guò)是一次純粹的hacking行為。
Python發(fā)展
Python 簡(jiǎn)介Python 是一個(gè)高層次的結(jié)合了解釋性、編譯性、互動(dòng)性和面向?qū)ο蟮哪_本語(yǔ)言。 Python 的設(shè)計(jì)具有很強(qiáng)的可讀性,相比其他語(yǔ)言經(jīng)常使用英文關(guān)鍵字,其他語(yǔ)言的一些標(biāo)點(diǎn)符號(hào),它具有比其他語(yǔ)言更有特色語(yǔ)法結(jié)構(gòu)。 Python 是一種解釋型語(yǔ)言: 這意味著開(kāi)發(fā)過(guò)程中沒(méi)有了編譯這個(gè)環(huán)節(jié)。類(lèi)似于PHP和Perl語(yǔ)言。 Python 是交互式語(yǔ)言: 這意味著,您可以在一個(gè) Python 提示符 >>> 后直接執(zhí)行代碼。 Python 是面向?qū)ο笳Z(yǔ)言: 這意味著Python支持面向?qū)ο蟮娘L(fēng)格或代碼封裝在對(duì)象的編程技術(shù)。 Python 是初學(xué)者的語(yǔ)言:Python 對(duì)初級(jí)程序員而言,是一種偉大的語(yǔ)言,它支持廣泛的應(yīng)用程序開(kāi)發(fā),從簡(jiǎn)單的文字處理到 WWW 瀏覽器再到游戲。
Python 發(fā)展歷史Python 是由 Guido van Rossum 在八十年代末和九十年代初,在荷蘭國(guó)家數(shù)學(xué)和計(jì)算機(jī)科學(xué)研究所設(shè)計(jì)出來(lái)的。 Python 本身也是由諸多其他語(yǔ)言發(fā)展而來(lái)的,這包括 ABC、Modula-3、C、C++、Algol-68、SmallTalk、Unix shell 和其他的腳本語(yǔ)言等等。 像 Perl 語(yǔ)言一樣,Python 源代碼同樣遵循 GPL(GNU General Public License)協(xié)議。 現(xiàn)在 Python 是由一個(gè)核心開(kāi)發(fā)團(tuán)隊(duì)在維護(hù),Guido van Rossum 仍然占據(jù)著至關(guān)重要的作用,指導(dǎo)其進(jìn)展。 Python 2.7 被確定為最后一個(gè) Python 2.x 版本,它除了支持 Python 2.x 語(yǔ)法外,還支持部分 Python 3.1 語(yǔ)法。
Python 優(yōu)點(diǎn)1.易于學(xué)習(xí):Python有相對(duì)較少的關(guān)鍵字,結(jié)構(gòu)簡(jiǎn)單,和一個(gè)明確定義的語(yǔ)法,學(xué)習(xí)起來(lái)更加簡(jiǎn)單。 2.易于閱讀:Python代碼定義的更清晰。 3.易于維護(hù):Python的成功在于它的源代碼是相當(dāng)容易維護(hù)的。 4.一個(gè)廣泛的標(biāo)準(zhǔn)庫(kù):Python的最大的優(yōu)勢(shì)之一是豐富的庫(kù),跨平臺(tái)的,在UNIX,Windows和Macintosh兼容很好。 5.互動(dòng)模式:互動(dòng)模式的支持,您可以從終端輸入執(zhí)行代碼并獲得結(jié)果的語(yǔ)言,互動(dòng)的測(cè)試和調(diào)試代碼片斷。 6.可移植:基于其開(kāi)放源代碼的特性,Python已經(jīng)被移植(也就是使其工作)到許多平臺(tái)。 7.可擴(kuò)展:如果你需要一段運(yùn)行很快的關(guān)鍵代碼,或者是想要編寫(xiě)一些不愿開(kāi)放的算法,你可以使用C或C++完成那部分程序,然后從你的Python程序中調(diào)用。 8.數(shù)據(jù)庫(kù):Python提供所有主要的商業(yè)數(shù)據(jù)庫(kù)的接口。 9.GUI編程:Python支持GUI可以創(chuàng)建和移植到許多系統(tǒng)調(diào)用。 10.可嵌入: 你可以將Python嵌入到C/C++程序,讓你的程序的用戶獲得"腳本化"的能力。
Python語(yǔ)言缺點(diǎn)Python基礎(chǔ)-面向?qū)ο?一)Python基礎(chǔ)-面向?qū)ο?一)面向?qū)ο缶幊探榻B如今主流的軟件開(kāi)發(fā)思想有兩種:一個(gè)是面向過(guò)程,另一個(gè)是面向?qū)ο?。面向過(guò)程出現(xiàn)得較早,典型代表為C語(yǔ)言,開(kāi)發(fā)中小型項(xiàng)目的效率很高,但是很難適用于如今主流的大中型項(xiàng)目開(kāi)發(fā)場(chǎng)景。面向?qū)ο髣t出現(xiàn)得更晚一些,典型代表為Java或C++等語(yǔ)言,更加適合用于大型開(kāi)發(fā)場(chǎng)景。兩種開(kāi)發(fā)思想各有長(zhǎng)短。 對(duì)于面向過(guò)程的思想: 需要實(shí)現(xiàn)一個(gè)功能的時(shí)候,看重的是開(kāi)發(fā)的步驟和過(guò)程,每一個(gè)步驟都需要自己親力親為,需要自己編寫(xiě)代碼(自己來(lái)做) 對(duì)于面向?qū)ο蟮乃枷耄寒?dāng)需要實(shí)現(xiàn)一個(gè)功能的時(shí)候,看重的并不是過(guò)程和步驟,而是關(guān)心誰(shuí)幫我做這件事(偷懶,找人幫我做) 面向?qū)ο蟮娜筇卣饔校悍庋b性、繼承性、多態(tài)性。 類(lèi)和對(duì)象面向?qū)ο缶幊痰?個(gè)非常重要的概念:類(lèi)和對(duì)象 對(duì)象是面向?qū)ο缶幊痰暮诵?,在使用?duì)象的過(guò)程中,為了將具有共同特征和行為的一組對(duì)象抽象定義,提出了另外一個(gè)新的概念——類(lèi) 1. 類(lèi) 我們學(xué)習(xí)編程語(yǔ)言,就是為了模擬現(xiàn)實(shí)世界中的事物,實(shí)現(xiàn)信息化來(lái)提高工作效率。例如銀行的業(yè)務(wù)系統(tǒng)、超市的結(jié)賬系統(tǒng)等,都是如此。 面向?qū)ο蟮恼Z(yǔ)言當(dāng)中,“類(lèi)”就是用來(lái)模擬現(xiàn)實(shí)事物的。 那么模擬現(xiàn)實(shí)世界的事物通常從兩方面模擬: 1.1,屬性:事物的特征描述信息,用于描述某個(gè)特征“是什么”。 靜 1.2,行為:事物的能力行動(dòng)方案,用于說(shuō)明事物“能做什么”。 2. 對(duì)象,某一個(gè)具體事物的存在就是對(duì)象,在現(xiàn)實(shí)世界中可以是看得見(jiàn)摸得著的。 3. 類(lèi)和對(duì)象之間的關(guān)系:類(lèi)就是創(chuàng)建對(duì)象的模板 4. 練習(xí):區(qū)分類(lèi)和對(duì)象 奔馳汽車(chē) 類(lèi) 奔馳smart 類(lèi) 張三的那輛奔馳smart 對(duì)象 狗 類(lèi) 大黃狗 類(lèi) 李四家那只大黃狗 對(duì)象 水果 類(lèi) 蘋(píng)果 類(lèi) 紅蘋(píng)果 類(lèi) 紅富士蘋(píng)果 類(lèi) 我嘴里吃了一半的蘋(píng)果 對(duì)象 5. 類(lèi)的構(gòu)成 類(lèi)(Class) 由3個(gè)部分構(gòu)成: 類(lèi)的名稱:類(lèi)名 類(lèi)的屬性:一組數(shù)據(jù) 類(lèi)的方法:允許對(duì)進(jìn)行操作的方法 (行為) 舉例: 1)人類(lèi)設(shè)計(jì),只關(guān)心3樣?xùn)|西: 事物名稱(類(lèi)名):人(Person) 屬性:身高(height)、年齡(age)... 方法(行為/功能):跑(run)、打架(fight)... 狗類(lèi)的設(shè)計(jì) 類(lèi)名:狗(Dog) 屬性:品種 、毛色、性別、名字、 腿兒的數(shù)量... 方法(行為/功能):叫 、跑、咬人、吃、搖尾巴... 6. 類(lèi)的抽象 如何把日常生活中的事物抽象成程序中的類(lèi)? 擁有相同(或者類(lèi)似)屬性和行為的對(duì)象都可以抽像出一個(gè)類(lèi) 方法:一般名詞都是類(lèi)(名詞提煉法) <1>坦克發(fā)射3顆炮彈轟掉了2架飛機(jī): 坦克--》可以抽象成 類(lèi) 炮彈--》可以抽象成類(lèi) 飛機(jī)-》可以抽象成類(lèi) <2>小明在公車(chē)上牽著一條叼著熱狗的狗 小明--》 人類(lèi) 公車(chē)--》 交通工具類(lèi) 熱狗--》 食物類(lèi) 狗--》 狗類(lèi) 定義類(lèi)定義一個(gè)類(lèi),格式如下: 1 2 3 4 | # class Hero: # 經(jīng)典類(lèi)(舊式類(lèi))定義形式
class Hero( object ): # 新式類(lèi)定義形式
def info( self ):
print ( "英雄不問(wèn)出處。" )
|
說(shuō)明:object 是Python 里所有類(lèi)的最頂級(jí)父類(lèi); info是一個(gè)實(shí)例方法,第一個(gè)參數(shù)一般是self,表示實(shí)例對(duì)象本身,當(dāng)然了可以將self換為其它的名字,其作用是一個(gè)變量 這個(gè)變量指向了實(shí)例對(duì)象 創(chuàng)建對(duì)象python中,可以根據(jù)已經(jīng)定義的類(lèi)去創(chuàng)建出一個(gè)或多個(gè)對(duì)象。 對(duì)象名1 = 類(lèi)名() 對(duì)象名2 = 類(lèi)名() 對(duì)象名3 = 類(lèi)名() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class Hero( object ):
"""info 是一個(gè)實(shí)例方法,類(lèi)對(duì)象可以調(diào)用實(shí)例方法,實(shí)例方法的第一個(gè)參數(shù)一定是self"""
def info( self ):
"""當(dāng)對(duì)象調(diào)用實(shí)例方法時(shí),Python會(huì)自動(dòng)將對(duì)象本身的引用做為參數(shù),
傳遞到實(shí)例方法的第一個(gè)參數(shù)self里"""
print ( self )
print ( "self各不同,對(duì)象是出處。" ) # Hero這個(gè)類(lèi) 實(shí)例化了一個(gè)對(duì)象 taidamier(泰達(dá)米爾)
taidamier = Hero()
# 對(duì)象調(diào)用實(shí)例方法info(),執(zhí)行info()里的代碼
# . 表示選擇屬性或者方法
taidamier.info() print (taidamier) # 打印對(duì)象,則默認(rèn)打印對(duì)象在內(nèi)存的地址,結(jié)果等同于info里的print(self)
print ( id (taidamier)) # id(taidamier) 則是內(nèi)存地址的十進(jìn)制形式表示 '''輸出結(jié)果
<__main__.Hero object at 0x7f96ea060e48>
self各不同,對(duì)象是出處。
<__main__.Hero object at 0x7f96ea060e48>
140286148087368
'''
|
添加和獲取對(duì)象的屬性1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | class Hero( object ):
"""定義了一個(gè)英雄類(lèi),可以移動(dòng)和攻擊"""
def move( self ):
"""實(shí)例方法"""
print ( "正在前往事發(fā)地點(diǎn)..." ) def attack( self ):
"""實(shí)例方法"""
print ( "發(fā)出了一招強(qiáng)力的普通攻擊..." ) # 實(shí)例化了一個(gè)英雄對(duì)象 泰達(dá)米爾
taidamier = Hero() # 給對(duì)象添加屬性,以及對(duì)應(yīng)的屬性值
taidamier.name = "泰達(dá)米爾" # 姓名
taidamier.hp = 2600 # 生命值
taidamier.atk = 450 # 攻擊力
taidamier.armor = 200 # 護(hù)甲值 # 通過(guò).成員選擇運(yùn)算符,獲取對(duì)象的屬性值
print ( "英雄 %s 的生命值 :%d" % (taidamier.name, taidamier.hp))
print ( "英雄 %s 的攻擊力 :%d" % (taidamier.name, taidamier.atk))
print ( "英雄 %s 的護(hù)甲值 :%d" % (taidamier.name, taidamier.armor)) # 通過(guò).成員選擇運(yùn)算符,獲取對(duì)象的實(shí)例方法
taidamier.move()
taidamier.attack() '''輸出結(jié)果
英雄 泰達(dá)米爾 的生命值 :2600
英雄 泰達(dá)米爾 的攻擊力 :450
英雄 泰達(dá)米爾 的護(hù)甲值 :200
正在前往事發(fā)地點(diǎn)...
發(fā)出了一招強(qiáng)力的普通攻擊...
'''
|
在方法內(nèi)通過(guò)self獲取對(duì)象屬性1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | class Hero( object ):
"""定義了一個(gè)英雄類(lèi),可以移動(dòng)和攻擊"""
def move( self ):
"""實(shí)例方法"""
print ( "正在前往事發(fā)地點(diǎn)..." ) def attack( self ):
"""實(shí)例方法"""
print ( "發(fā)出了一招強(qiáng)力的普通攻擊..." ) def info( self ):
"""在類(lèi)的實(shí)例方法中,通過(guò)self獲取該對(duì)象的屬性"""
print ( "英雄 %s 的生命值 :%d" % ( self .name, self .hp))
print ( "英雄 %s 的攻擊力 :%d" % ( self .name, self .atk))
print ( "英雄 %s 的護(hù)甲值 :%d" % ( self .name, self .armor)) # 實(shí)例化了一個(gè)英雄對(duì)象 泰達(dá)米爾
taidamier = Hero() # 給對(duì)象添加屬性,以及對(duì)應(yīng)的屬性值
taidamier.name = "泰達(dá)米爾" # 姓名
taidamier.hp = 2600 # 生命值
taidamier.atk = 450 # 攻擊力
taidamier.armor = 200 # 護(hù)甲值 # 通過(guò).成員選擇運(yùn)算符,獲取對(duì)象的實(shí)例方法
taidamier.info() # 只需要調(diào)用實(shí)例方法info(),即可獲取英雄的屬性
taidamier.move()
taidamier.attack() '''輸出結(jié)果
英雄 泰達(dá)米爾 的生命值 :2600
英雄 泰達(dá)米爾 的攻擊力 :450
英雄 泰達(dá)米爾 的護(hù)甲值 :200
正在前往事發(fā)地點(diǎn)...
發(fā)出了一招強(qiáng)力的普通攻擊...
'''
|
創(chuàng)建對(duì)象后再去添加屬性有點(diǎn)不合適,有沒(méi)有簡(jiǎn)單的辦法,可以在創(chuàng)建對(duì)象的時(shí)候,就已經(jīng)擁有這些屬性? __init__()方法Python的類(lèi)里提供的,兩個(gè)下劃線開(kāi)始,兩個(gè)下劃線結(jié)束的方法,就是魔法方法,__init__()就是一個(gè)魔法方法,通常用來(lái)做屬性初始化 或 賦值 操作。 如果類(lèi)面沒(méi)有寫(xiě)__init__方法,Python會(huì)自動(dòng)創(chuàng)建,但是不執(zhí)行任何操作,如果為了能夠在完成自己想要的功能,可以自己定義__init__方法,所以一個(gè)類(lèi)里無(wú)論自己是否編寫(xiě)__init__方法,一定有__init__方法。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | class Hero( object ):
def __init__( self ):
""" 方法,用來(lái)做變量初始化 或 賦值 操作,在類(lèi)實(shí)例化對(duì)象的時(shí)候,會(huì)被自動(dòng)調(diào)用"""
self .name = "泰達(dá)米爾" # 姓名
self .hp = 2600 # 生命值
self .atk = 450 # 攻擊力
self .armor = 200 # 護(hù)甲值 def move( self ):
"""實(shí)例方法"""
print ( "正在前往事發(fā)地點(diǎn)..." ) def attack( self ):
"""實(shí)例方法"""
print ( "發(fā)出了一招強(qiáng)力的普通攻擊..." ) taidamier = Hero()
# 實(shí)例化了一個(gè)英雄對(duì)象,并自動(dòng)調(diào)用__init__()方法
print ( '姓名:%s,生命值:%d,攻擊力:%d,護(hù)甲值:%d' % (taidamier.name,taidamier.hp,taidamier.atk,taidamier.armor, ))
# 通過(guò).成員選擇運(yùn)算符,獲取對(duì)象的實(shí)例方法
taidamier.move()
taidamier.attack()
'''運(yùn)行結(jié)果
姓名:泰達(dá)米爾,生命值:2600,攻擊力:450,護(hù)甲值:200
正在前往事發(fā)地點(diǎn)...
發(fā)出了一招強(qiáng)力的普通攻擊...
'''
|
__init__()方法,在創(chuàng)建一個(gè)對(duì)象時(shí)默認(rèn)被調(diào)用,不需要手動(dòng)調(diào)用 __init__(self)中的self參數(shù),不需要開(kāi)發(fā)者傳遞,python解釋器會(huì)自動(dòng)把當(dāng)前的對(duì)象引用傳遞過(guò)去。 在類(lèi)的方法里定義屬性的固定值,則每個(gè)對(duì)象實(shí)例變量的屬性值都是相同的。 一個(gè)游戲里往往有很多不同的英雄,能否讓實(shí)例化的每個(gè)對(duì)象,都有不同的屬性值呢? 有參數(shù)的__init__()方法通過(guò)一個(gè)類(lèi),可以創(chuàng)建多個(gè)對(duì)象,就好比 通過(guò)一個(gè)模具創(chuàng)建多個(gè)實(shí)體一樣 __init__(self)中,默認(rèn)有1個(gè)參數(shù)名字為self,假如在創(chuàng)建對(duì)象時(shí)傳遞了2個(gè)實(shí)參,那么__init__(self)中除了self作為第一個(gè)形參外還需要2個(gè)形參,例如__init__(self,x,y) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | class Hero( object ):
"""定義了一個(gè)英雄類(lèi),可以移動(dòng)和攻擊""" def __init__( self , name, skill, hp, atk, armor):
""" __init__() 方法,用來(lái)做變量初始化 或 賦值 操作"""
# 英雄名
self .name = name
# 技能
self .skill = skill
# 生命值:
self .hp = hp
# 攻擊力
self .atk = atk
# 護(hù)甲值
self .armor = armor def move( self ):
"""實(shí)例方法"""
print ( "%s 正在前往事發(fā)地點(diǎn)..." % self .name) def attack( self ):
"""實(shí)例方法"""
print ( "發(fā)出了一招強(qiáng)力的%s..." % self .skill) def info( self ):
print ( "英雄 %s 的生命值 :%d" % ( self .name, self .hp))
print ( "英雄 %s 的攻擊力 :%d" % ( self .name, self .atk))
print ( "英雄 %s 的護(hù)甲值 :%d" % ( self .name, self .armor)) # 實(shí)例化英雄對(duì)象時(shí),參數(shù)會(huì)傳遞到對(duì)象的__init__()方法里
taidamier = Hero( "泰達(dá)米爾" , "旋風(fēng)斬" , 2600 , 450 , 200 )
gailun = Hero( "蓋倫" , "大寶劍" , 4200 , 260 , 400 ) print (gailun)
print (taidamier) # 不同對(duì)象的屬性值的單獨(dú)保存
print ( id (taidamier.name))
print ( id (gailun.name)) # 同一個(gè)類(lèi)的不同對(duì)象,實(shí)例方法共享
print ( id (taidamier.move()))
print ( id (gailun.move())) '''結(jié)果
<__main__.Hero object at 0x7f5681bde128>
<__main__.Hero object at 0x7f5681bd9ac8>
140009521155040
140009521270576
泰達(dá)米爾 正在前往事發(fā)地點(diǎn)...
10722752
蓋倫 正在前往事發(fā)地點(diǎn)...
10722752
'''
|
1,在類(lèi)內(nèi)部獲取 屬性 和 實(shí)例方法,通過(guò)self獲??; 2,在類(lèi)外部獲取 屬性 和 實(shí)例方法,通過(guò)對(duì)象名獲取。 3,如果一個(gè)類(lèi)有多個(gè)對(duì)象,每個(gè)對(duì)象的屬性是各自保存的,都有各自獨(dú)立的地址; 4,但是實(shí)例方法是所有對(duì)象共享的,只占用一份內(nèi)存空間。類(lèi)會(huì)通過(guò)self來(lái)判斷是哪個(gè)對(duì)象調(diào)用了實(shí)例方法。
最后修改:2020年3月1日 16:39 Python基礎(chǔ)-面向?qū)ο?二)__str__()方法這個(gè)方法是一個(gè)魔法方法 (Magic Method) ,用來(lái)顯示信息 該方法需要 return 一個(gè)數(shù)據(jù),并且只有self一個(gè)參數(shù),當(dāng)在類(lèi)的外部 print(對(duì)象) 則打印這個(gè)數(shù)據(jù) 當(dāng)類(lèi)的實(shí)例化對(duì)象如果沒(méi)有__str__ 則默認(rèn)打印 對(duì)象在內(nèi)存的地址。如果擁有 __str__ 方法后,那么打印對(duì)象則打印 __str__ 的返回值。 查看類(lèi)的文檔說(shuō)明,也就是類(lèi)的注釋:print(Hero.__doc__) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | class Hero( object ):
"""定義了一個(gè)英雄類(lèi),可以移動(dòng)和攻擊""" def __init__( self , name, skill, hp, atk, armor):
""" __init__() 方法,用來(lái)做變量初始化 或 賦值 操作"""
# 英雄名
self .name = name # 實(shí)例變量
# 技能
self .skill = skill
# 生命值:
self .hp = hp # 實(shí)例變量
# 攻擊力
self .atk = atk
# 護(hù)甲值
self .armor = armor def move( self ):
"""實(shí)例方法"""
print ( "%s 正在前往事發(fā)地點(diǎn)..." % self .name) def attack( self ):
"""實(shí)例方法"""
print ( "發(fā)出了一招強(qiáng)力的%s..." % self .skill) def __str__( self ):
"""
這個(gè)方法是一個(gè)魔法方法 (Magic Method) ,用來(lái)顯示信息
該方法需要 return 一個(gè)數(shù)據(jù),并且只有self一個(gè)參數(shù),當(dāng)在類(lèi)的外部 print(對(duì)象) 則打印這個(gè)數(shù)據(jù)
"""
return "英雄【%s】的數(shù)據(jù): 生命值 %d, 攻擊力 %d, 護(hù)甲值 %d" % ( self .name, self .hp, self .atk, self .armor) taidamier = Hero( "泰達(dá)米爾" , "旋風(fēng)斬" , 2600 , 450 , 200 )
gailun = Hero( "蓋倫" , "大寶劍" , 4200 , 260 , 400 ) # 如果沒(méi)有__str__ 則默認(rèn)打印 對(duì)象在內(nèi)存的地址。
# 當(dāng)類(lèi)的實(shí)例化對(duì)象 擁有 __str__ 方法后,那么打印對(duì)象則打印 __str__ 的返回值。
print (taidamier) # 英雄【泰達(dá)米爾】的數(shù)據(jù): 生命值 2600, 攻擊力 450, 護(hù)甲值 200
print (gailun) # 英雄【蓋倫】的數(shù)據(jù): 生命值 4200, 攻擊力 260, 護(hù)甲值 400 # 查看類(lèi)的文檔說(shuō)明,也就是類(lèi)的注釋
print (Hero.__doc__) # 定義了一個(gè)英雄類(lèi),可以移動(dòng)和攻擊
|
在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法。 當(dāng)使用print輸出對(duì)象的時(shí)候,默認(rèn)打印對(duì)象的內(nèi)存地址。如果類(lèi)定義了__str__(self)方法,那么就會(huì)打印從在這個(gè)方法中 return 的數(shù)據(jù)。 __str__方法通常返回一個(gè)字符串,作為這個(gè)對(duì)象的描述信息 __del__()方法創(chuàng)建對(duì)象后,python解釋器默認(rèn)調(diào)用__init__()方法; 當(dāng)刪除對(duì)象時(shí),python解釋器也會(huì)默認(rèn)調(diào)用一個(gè)方法,這個(gè)方法為_(kāi)_del__()方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | class Hero( object ): # 初始化方法
# 創(chuàng)建完對(duì)象后會(huì)自動(dòng)被調(diào)用
def __init__( self , name):
print ( '__init__方法被調(diào)用' )
self .name = name # 當(dāng)對(duì)象被刪除時(shí),會(huì)自動(dòng)被調(diào)用
def __del__( self ):
print ( "__del__方法被調(diào)用" )
print ( "%s 被 GM 干掉了..." % self .name) # 創(chuàng)建對(duì)象
taidamier = Hero( "泰達(dá)米爾" ) # 刪除對(duì)象
print ( "%d 被刪除1次" % id (taidamier))
del (taidamier) print ( "--" * 10 ) gailun = Hero( "蓋倫" )
gailun1 = gailun
gailun2 = gailun print ( "%d 被刪除1次" % id (gailun))
del (gailun) print ( "%d 被刪除1次" % id (gailun1))
del (gailun1) print ( "%d 被刪除1次" % id (gailun2))
del (gailun2)
'''
輸出結(jié)果
__init__方法被調(diào)用
139881105243440 被刪除1次
__del__方法被調(diào)用
泰達(dá)米爾 被 GM 干掉了...
--------------------
__init__方法被調(diào)用
139881105242488 被刪除1次
139881105242488 被刪除1次
139881105242488 被刪除1次
__del__方法被調(diào)用
蓋倫 被 GM 干掉了...
'''
|
當(dāng)有變量保存了一個(gè)對(duì)象的引用時(shí),此對(duì)象的引用計(jì)數(shù)就會(huì)加1; 當(dāng)使用del() 刪除變量指向的對(duì)象時(shí),則會(huì)減少對(duì)象的引用計(jì)數(shù)。如果對(duì)象的引用計(jì)數(shù)不為1,那么會(huì)讓這個(gè)對(duì)象的引用計(jì)數(shù)減1,當(dāng)對(duì)象的引用計(jì)數(shù)為0的時(shí)候,則對(duì)象才會(huì)被真正刪除(內(nèi)存被回收)。 面向?qū)ο髮?shí)例:烤地瓜目標(biāo) 強(qiáng)化面向?qū)ο缶幊痰脑O(shè)計(jì)能力,進(jìn)一步理解類(lèi)、屬性、方法的構(gòu)建場(chǎng)景 強(qiáng)化對(duì)self的理解,方法中使用self可以獲取和修改屬性 烤地瓜規(guī)則: 1.地瓜有自己的狀態(tài),默認(rèn)是生的,地瓜可以進(jìn)行燒烤 2地瓜有自己燒烤的總時(shí)間,由每次燒烤的時(shí)間累加得出 3.地瓜燒烤時(shí),需要提供本次燒烤的時(shí)間 4.地瓜燒烤時(shí),地瓜狀態(tài)隨著燒烤總時(shí)間的變化而改變: [0, 3)生的、[3, 6)半生不熟、[6, 8)熟了、>=8烤糊了 5.輸出地瓜信息時(shí),可以顯示地瓜的狀態(tài)和燒烤的總時(shí)間 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | # 新型一個(gè)新型類(lèi)SweetPotato
class SweetPotato( object ):
'''
烤地瓜的文檔說(shuō)明
'''
# 初始化屬性CookeLevel(一共烤的時(shí)間),CookedString(地瓜狀態(tài)),Condiments(調(diào)料列表)
def __init__( self ):
self .CookedLevel = 0
self .CookedString = '生的'
self .Condiments = []
# 烤地瓜的方法
def cook( self ,time):
self .CookedLevel + = time
if self .CookedLevel > 8 :
self .CookedString = '烤糊了'
elif self .CookedLevel > 5 :
self .CookedString = '烤好了'
elif self .CookedLevel > 3 :
self .CookedString = '烤的半生不熟'
else :
self .CookedString = '生的'
# 添加調(diào)料的方法
def add_condiments( self ,condiments):
self .Condiments.append(condiments)
# print的輸出信息
def __str__( self ):
if len ( self .Condiments) > 0 :
str_Condiments = ',' .join( self .Condiments) # 列表轉(zhuǎn)字符串
return '地瓜烤了%d分鐘,%s,調(diào)料是%s' % ( self .CookedLevel, self .CookedString,str_Condiments)
else :
return '地瓜烤了%d分鐘,%s,沒(méi)有調(diào)料' % ( self .CookedLevel, self .CookedString) print (SweetPotato.__doc__) # 查看類(lèi)的文檔說(shuō)明:烤地瓜的文檔說(shuō)明
mysweetpotao = SweetPotato() # 實(shí)例化一個(gè)對(duì)象
mysweetpotao.cook( 2 )
print (mysweetpotao) # 地瓜烤了2分鐘,生的,沒(méi)有調(diào)料 mysweetpotao.cook( 2 )
mysweetpotao.add_condiments( '番茄醬' )
print (mysweetpotao) # 地瓜烤了4分鐘,烤的半生不熟,調(diào)料是番茄醬 mysweetpotao.cook( 3 )
mysweetpotao.add_condiments( '辣椒醬' )
print (mysweetpotao) # 地瓜烤了7分鐘,烤好了,調(diào)料是番茄醬,辣椒醬 mysweetpotao.cook( 2 )
mysweetpotao.add_condiments( '芥末' )
print (mysweetpotao) #地瓜烤了9分鐘,烤糊了,調(diào)料是番茄醬,辣椒醬,芥末
|
最后修改:2020年3月1日 22:21 Python基礎(chǔ)-面向?qū)ο?三)繼承的概念在程序中,繼承描述的是多個(gè)類(lèi)之間的所屬關(guān)系。 如果一個(gè)類(lèi)A里面的屬性和方法可以復(fù)用,則可以通過(guò)繼承的方式,傳遞到類(lèi)B里。 那么類(lèi)A就是基類(lèi),也叫做父類(lèi);類(lèi)B就是派生類(lèi),也叫做子類(lèi)。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # 父類(lèi)
class A( object ):
def __init__( self ):
self .num = 10
def sum ( self ):
return self .num + 10 # 子類(lèi)
class B(A):
pass b = B()
print (b.num) # 10
print (b. sum ()) # 20
|
單繼承:子類(lèi)只繼承一個(gè)父類(lèi)故事情節(jié):煎餅果子老師傅在煎餅果子界摸爬滾打幾十年,擁有一身精湛的煎餅果子技術(shù),并總結(jié)了一套"古法煎餅果子配方"??墒抢蠋煾的赀~已久,在去世之前希望把自己的配方傳承下去,于是老師傅把配方傳給他的徒弟大貓... 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 定義一個(gè)Master父類(lèi)
class Master( object ):
def __init__( self ):
# 屬性
self .gufa = '古法煎餅果子配方'
# 方法
def make_cake( self ):
print ( '按照%s制作古法煎餅果子' % self .gufa) # 定義一個(gè)Prentice子類(lèi),繼承父類(lèi)Master
class Prentice(Master):
# 子類(lèi)可以繼承父類(lèi)所有的屬性和方法,哪怕子類(lèi)沒(méi)有自己的屬性和方法,也可以使用父類(lèi)的屬性和方法。
pass # 創(chuàng)建子類(lèi)實(shí)例對(duì)象
p = Prentice()
# 子類(lèi)對(duì)象可以直接使用父類(lèi)的屬性
print (p.gufa) # 古法煎餅果子配方
# 子類(lèi)對(duì)象可以直接使用父類(lèi)的方法
p.make_cake() # 按照古法煎餅果子配方制作古法煎餅果子
|
雖然子類(lèi)沒(méi)有定義__init__方法初始化屬性,也沒(méi)有定義實(shí)例方法,但是父類(lèi)有。所以只要?jiǎng)?chuàng)建子類(lèi)的對(duì)象,就默認(rèn)執(zhí)行了那個(gè)繼承過(guò)來(lái)的__init__方法 子類(lèi)在繼承的時(shí)候,在定義類(lèi)時(shí),小括號(hào)()中為父類(lèi)的名字 父類(lèi)的屬性、方法,會(huì)被繼承給子類(lèi) 多繼承:子類(lèi)繼承多個(gè)父類(lèi)劇情發(fā)展:大貓掌握了師傅的配方,可以制作古法煎餅果子。但是大貓是個(gè)愛(ài)學(xué)習(xí)的好孩子,他希望學(xué)到更多的煎餅果子的做法,于是通過(guò)百度搜索,找到了一家煎餅果子培訓(xùn)學(xué)校。(多繼承) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | # 定義一個(gè)Master父類(lèi)
class Master( object ):
def __init__( self ):
# 屬性
self .gufa = '古法煎餅果子配方'
# 方法
def make_cake( self ):
print ( '按照%s制作古法煎餅果子' % self .gufa)
def eat_master( self ):
print ( '在師傅家吃飯' ) # 定義一個(gè)School父類(lèi)
class School( object ):
def __init__( self ):
self .gufa = '現(xiàn)代煎餅果子配方'
def make_cake( self ):
print ( '按照%s制作現(xiàn)代煎餅果子' % self .gufa)
def eat_school( self ):
print ( '在學(xué)校吃飯' ) # 定義一個(gè)Prentice子類(lèi),繼承父類(lèi)Master,School
class Prentice(Master,School):
# 子類(lèi)可以繼承兩個(gè)父類(lèi)所有的屬性和方法,哪怕子類(lèi)沒(méi)有自己的屬性和方法,也可以使用兩個(gè)父類(lèi)的屬性和方法。
pass # 創(chuàng)建子類(lèi)實(shí)例對(duì)象
p = Prentice()
# 子類(lèi)對(duì)象可以直接使用父類(lèi)的屬性,兩個(gè)父類(lèi)的屬性名相同,默認(rèn)調(diào)用第一個(gè)父類(lèi)
print (p.gufa) # 古法煎餅果子配方
# 子類(lèi)對(duì)象可以直接使用父類(lèi)的方法
p.make_cake() # 按照古法煎餅果子配方制作古法煎餅果子,兩個(gè)父類(lèi)的屬性名相同時(shí),根據(jù)類(lèi)的魔法屬性mro的順序來(lái)查找 # 兩個(gè)父類(lèi)方法不相同時(shí),兩個(gè)都可以調(diào)用出來(lái)
p.eat_master() # 在師傅家吃飯
p.eat_school() # 在學(xué)校吃飯 # 注意:如果多個(gè)父類(lèi)中有同名的 屬性和方法,則根據(jù)類(lèi)的魔法屬性mro的順序來(lái)查找
print (Prentice.__mro__)
# 結(jié)果(<class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
|
多繼承可以繼承多個(gè)父類(lèi),也繼承了所有父類(lèi)的屬性和方法 注意:如果多個(gè)父類(lèi)中有同名的 屬性和方法,則根據(jù)類(lèi)的魔法屬性mro的順序來(lái)查找 多個(gè)父類(lèi)中,不重名的屬性和方法,不會(huì)有任何影響。 子類(lèi)重寫(xiě)父類(lèi)的同名屬性和方法劇情發(fā)展:大貓掌握了 師傅的配方 和 學(xué)校的配方,通過(guò)研究,大貓?jiān)趦蓚€(gè)配方的基礎(chǔ)上,創(chuàng)建了一種全新的煎餅果子配方,稱之為 "貓氏煎餅果子配方"。(子類(lèi)重寫(xiě)父類(lèi)同名屬性和方法) 如果子類(lèi)和父類(lèi)的方法名或?qū)傩悦嗤?,則默認(rèn)使用子類(lèi)的,叫 子類(lèi)重寫(xiě)父類(lèi)的同名方法和屬性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # 定義一個(gè)Master父類(lèi)
class Master( object ):
def __init__( self ):
# 屬性
self .gufa = '古法煎餅果子配方'
# 方法
def make_cake( self ):
print ( '按照%s制作古法煎餅果子' % self .gufa)
def eat_master( self ):
print ( '在師傅家吃飯' ) # 定義一個(gè)School父類(lèi)
class School( object ):
def __init__( self ):
self .gufa = '現(xiàn)代煎餅果子配方'
def make_cake( self ):
print ( '按照%s制作現(xiàn)代煎餅果子' % self .gufa)
def eat_school( self ):
print ( '在學(xué)校吃飯' ) # 定義一個(gè)Prentice子類(lèi),繼承父類(lèi)Master,School
class Prentice(Master,School):
# 子類(lèi)重寫(xiě)了屬性和方法
def __init__( self ):
self .gufa = '貓式煎餅果子配方'
def make_cake( self ):
print ( '用%s貓式煎餅果子配方制作煎餅果子' % self .gufa) # 創(chuàng)建子類(lèi)實(shí)例對(duì)象
p = Prentice()
print (p.gufa) # 貓式煎餅果子配方,子類(lèi)重寫(xiě)了父類(lèi)的屬性,用子類(lèi)的屬性
p.make_cake() # 用貓式煎餅果子配方貓式煎餅果子配方制作煎餅果子,子類(lèi)重寫(xiě)了父類(lèi)的方法,用子類(lèi)的方法 # 注意:如果重寫(xiě)了父類(lèi)中有屬性或方法,則默認(rèn)使用子類(lèi)的屬性或方法(根據(jù)類(lèi)的魔法屬性mro的順序來(lái)查找)
print (Prentice.__mro__)
# 結(jié)果(<class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>)
|
子類(lèi)調(diào)用父類(lèi)同名屬性和方法劇情發(fā)展:大貓的新配方大受歡迎,但是有些顧客希望也能吃到古法配方和 現(xiàn)代配方 的煎餅果子...(子類(lèi)調(diào)用父類(lèi)的同名屬性和方法) 如果子類(lèi)和父類(lèi)的方法名或?qū)傩悦嗤?,則默認(rèn)使用子類(lèi)的,叫子類(lèi)重寫(xiě)父類(lèi)的同名方法和屬性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | # 定義一個(gè)Master父類(lèi)
class Master( object ):
def __init__( self ):
# 屬性
self .gufa = '古法煎餅果子配方'
# 方法
def make_cake( self ):
print ( '按照%s制作古法煎餅果子' % self .gufa)
def eat_master( self ):
print ( '在師傅家吃飯' ) # 定義一個(gè)School父類(lèi)
class School( object ):
def __init__( self ):
self .gufa = '現(xiàn)代煎餅果子配方'
def make_cake( self ):
print ( '按照%s制作現(xiàn)代煎餅果子' % self .gufa)
def eat_school( self ):
print ( '在學(xué)校吃飯' ) # 定義一個(gè)Prentice子類(lèi),繼承父類(lèi)Master,School
class Prentice(Master,School):
# 子類(lèi)重寫(xiě)了屬性和方法
def __init__( self ):
self .gufa = '貓式煎餅果子配方'
def make_cake( self ):
print ( '用%s貓式煎餅果子配方制作煎餅果子' % self .gufa)
# 獲取Master的屬性和方法
def make_master_cake( self ):
Master.__init__( self )
Master.make_cake( self ) # 獲取School 的屬性和方法
def make_school_cake( self ):
School.__init__( self )
School.make_cake( self ) # 創(chuàng)建子類(lèi)實(shí)例對(duì)象
p = Prentice()
print (p.gufa) # 貓式煎餅果子配方,子類(lèi)重寫(xiě)了父類(lèi)的屬性,用子類(lèi)的屬性
p.make_cake() # 用貓式煎餅果子配方貓式煎餅果子配方制作煎餅果子,子類(lèi)重寫(xiě)了父類(lèi)的方法,用子類(lèi)的方法 # 注意:如果重寫(xiě)了父類(lèi)中有屬性或方法,則默認(rèn)使用子類(lèi)的屬性或方法(根據(jù)類(lèi)的魔法屬性mro的順序來(lái)查找)
print (Prentice.__mro__)
# 結(jié)果(<class '__main__.Prentice'>, <class '__main__.Master'>, <class '__main__.School'>, <class 'object'>) # 調(diào)用Master的屬性和方法
p.make_master_cake() # 按照古法煎餅果子配方制作古法煎餅果子
print (p.gufa) # 執(zhí)行Master類(lèi)的__init__方法后,self.kongfu屬性:古法煎餅果子配方 # 調(diào)用School的屬性和方法
p.make_school_cake() # 按照現(xiàn)代煎餅果子配方制作現(xiàn)代煎餅果子
print (p.gufa) # 執(zhí)行School類(lèi)的__init__方法后,self.kongfu屬性:現(xiàn)代煎餅果子配方
|
super()的使用子類(lèi)繼承了多個(gè)父類(lèi),如果父類(lèi)類(lèi)名修改了,那么子類(lèi)也要涉及多次修改。而且需要重復(fù)寫(xiě)多次調(diào)用,顯得代碼臃腫。 使用super() 可以逐一調(diào)用所有的父類(lèi)方法,并且只執(zhí)行一次。調(diào)用順序遵循 mro 類(lèi)屬性的順序。 注意:如果繼承了多個(gè)父類(lèi),且父類(lèi)都有同名方法,則默認(rèn)只執(zhí)行第一個(gè)父類(lèi)的(同名方法只執(zhí)行一次,目前super()不支持執(zhí)行多個(gè)父類(lèi)的同名方法) super() 在Python2.3之后才有的機(jī)制,用于通常單繼承的多層繼承。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | # 定義一個(gè)Master父類(lèi)
class Master( object ):
def __init__( self ):
# 屬性
self .gufa = '古法煎餅果子配方' # 方法
def make_cake( self ):
print ( '按照%s制作古法煎餅果子' % self .gufa) def eat_master( self ):
print ( '在師傅家吃飯' ) # 定義一個(gè)School父類(lèi)
class School( object ):
def __init__( self ):
self .gufa = '現(xiàn)代煎餅果子配方' def make_cake( self ):
print ( '按照%s制作現(xiàn)代煎餅果子' % self .gufa) def eat_school( self ):
print ( '在學(xué)校吃飯' ) # 定義一個(gè)Prentice子類(lèi),繼承父類(lèi)Master,School
class Prentice(Master, School):
# 子類(lèi)重寫(xiě)了屬性和方法
def __init__( self ):
self .gufa = '貓式煎餅果子配方' def make_cake( self ):
print ( '用%s制作煎餅果子' % self .gufa) def make_all_cake( self ):
# 方式1. 指定執(zhí)行父類(lèi)的方法(代碼臃腫)
# School.__init__(self)
# School.make_cake(self)
#
# Master.__init__(self)
# Master.make_cake(self)
#
# self.__init__()
# self.make_cake() # 方法2. super() 帶參數(shù)版本,只支持新式類(lèi)
# super(Prentice, self).__init__() # 執(zhí)行父類(lèi)的 __init__方法
# super(Prentice, self).make_cake()
# self.make_cake() # 方法3. super()的簡(jiǎn)化版,只支持新式類(lèi)
super ().__init__() # 執(zhí)行父類(lèi)的 __init__方法
super ().make_cake() # 執(zhí)行父類(lèi)的 實(shí)例方法
self .__init__() # 執(zhí)行本類(lèi)的實(shí)例方法
self .make_cake() # 執(zhí)行本類(lèi)的實(shí)例方法 # 創(chuàng)建子類(lèi)實(shí)例對(duì)象
p = Prentice()
print (p.gufa)
p.make_all_cake()
|
多層繼承劇情發(fā)展:大貓的煎餅果子店非常紅火,終于有一天,他成了世界首富??!但是他也老了,所以他希望把 師傅的配方 和 學(xué)校的配方 以及自己的配方 繼續(xù)傳承下去...(多層繼承) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | # 定義一個(gè)Master父類(lèi)
class Master( object ):
def __init__( self ):
# 屬性
self .gufa = '古法煎餅果子配方'
# 方法
def make_cake( self ):
print ( '按照%s制作古法煎餅果子' % self .gufa)
def eat_master( self ):
print ( '在師傅家吃飯' ) # 定義一個(gè)School父類(lèi)
class School( object ):
def __init__( self ):
self .gufa = '現(xiàn)代煎餅果子配方'
def make_cake( self ):
print ( '按照%s制作現(xiàn)代煎餅果子' % self .gufa)
def eat_school( self ):
print ( '在學(xué)校吃飯' ) # 定義一個(gè)Prentice子類(lèi),繼承父類(lèi)Master,School
class Prentice(Master,School):
# 子類(lèi)重寫(xiě)了屬性和方法
def __init__( self ):
self .gufa = '貓式煎餅果子配方'
self .money = 1000 # 億美金
def make_cake( self ):
print ( '用%s配方制作煎餅果子' % self .gufa)
# 獲取Master的屬性和方法
def make_master_cake( self ):
Master.__init__( self )
Master.make_cake( self ) # 獲取School 的屬性和方法
def make_school_cake( self ):
School.__init__( self )
School.make_cake( self )
# 新建一個(gè)大貓徒弟的類(lèi),繼承大貓類(lèi)Prentice
class PrenticePrentice(Prentice):
pass # 創(chuàng)建大貓徒弟的實(shí)例對(duì)象
pp = PrenticePrentice()
pp.make_cake() # 用貓式煎餅果子配方配方制作煎餅果子
print (pp.gufa) # 貓式煎餅果子配方
pp.make_master_cake() # 按照古法煎餅果子配方制作古法煎餅果子
print (pp.gufa) # 古法煎餅果子配方
pp.make_school_cake() # 按照現(xiàn)代煎餅果子配方制作現(xiàn)代煎餅果子
print (pp.gufa) # 現(xiàn)代煎餅果子配方
|
最后修改:2020年3月2日 03:23 Python基礎(chǔ)-面向?qū)ο?四)私有權(quán)限面向?qū)ο笕筇匦裕悍庋b、繼承、多態(tài) 封裝的意義 1,將屬性和方法放到一起做為一個(gè)整體,然后通過(guò)實(shí)例化對(duì)象來(lái)處理; 2,隱藏內(nèi)部實(shí)現(xiàn)細(xì)節(jié),只需要和對(duì)象及其屬性和方法交互就可以了; 3,對(duì)類(lèi)的屬性和方法增加 訪問(wèn)權(quán)限控制。 私有權(quán)限:在屬性名和方法名 前面 加上兩個(gè)下劃線 __ 1,類(lèi)的私有屬性 和 私有方法,都不能通過(guò)對(duì)象直接訪問(wèn),但是可以在本類(lèi)內(nèi)部訪問(wèn); 2,類(lèi)的私有屬性 和 私有方法,都不會(huì)被子類(lèi)繼承,子類(lèi)也無(wú)法訪問(wèn); 3,私有屬性 和 私有方法 往往用來(lái)處理類(lèi)的內(nèi)部事情,不通過(guò)對(duì)象處理,起到安全作用。 劇情發(fā)展: 大貓覺(jué)得配方傳承下去沒(méi)問(wèn)題,但是錢(qián)是辛辛苦苦掙得血汗錢(qián),不想傳給徒弟。(私有權(quán)限) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | # 定義一個(gè)Master父類(lèi)
class Master( object ):
def __init__( self ):
# 屬性
self .gufa = '古法煎餅果子配方'
# 方法
def make_cake( self ):
print ( '按照%s制作古法煎餅果子' % self .gufa)
def eat_master( self ):
print ( '在師傅家吃飯' )
# 定義一個(gè)School父類(lèi)
class School( object ):
def __init__( self ):
self .gufa = '現(xiàn)代煎餅果子配方'
def make_cake( self ):
print ( '按照%s制作現(xiàn)代煎餅果子' % self .gufa)
def eat_school( self ):
print ( '在學(xué)校吃飯' )
# 定義一個(gè)Prentice子類(lèi),繼承父類(lèi)Master,School
class Prentice(Master, School):
# 子類(lèi)重寫(xiě)了屬性和方法
def __init__( self ):
self .gufa = '貓式煎餅果子配方'
self .__money = 1000 # 億美金
def make_cake( self ):
print ( '用%s配方制作煎餅果子' % self .gufa)
# 獲取Master的屬性和方法
def make_master_cake( self ):
Master.__init__( self )
Master.make_cake( self )
# 獲取School 的屬性和方法
def make_school_cake( self ):
School.__init__( self )
School.make_cake( self )
# 新建一個(gè)大貓徒弟的類(lèi),繼承大貓類(lèi)Prentice
class PrenticePrentice(Prentice):
pass
# 創(chuàng)建大貓徒弟的實(shí)例對(duì)象
pp = PrenticePrentice()
pp.make_cake() # 用貓式煎餅果子配方配方制作煎餅果子
print (pp.gufa) # 貓式煎餅果子配方
pp.make_master_cake() # 按照古法煎餅果子配方制作古法煎餅果子
print (pp.gufa) # 古法煎餅果子配方
pp.make_school_cake() # 按照現(xiàn)代煎餅果子配方制作現(xiàn)代煎餅果子
print (pp.gufa) # 現(xiàn)代煎餅果子配方
#monye式私有屬性,實(shí)例化繼承不了
print (pp.__money) # 繼承大貓的錢(qián),出錯(cuò):AttributeError: 'PrenticePrentice' object has no attribute '__money'
|
Python是以屬性命名方式來(lái)區(qū)分,如果在屬性和方法名前面加了2個(gè)下劃線'__',則表明該屬性和方法是私有權(quán)限,否則為公有權(quán)限。 修改私有屬性的值如果需要修改一個(gè)對(duì)象的屬性值,通常有2種方法: 1,對(duì)象名.屬性名 = 數(shù)據(jù) ----> 直接修改 2,對(duì)象名.方法名() ----> 間接修改 私有屬性不能直接訪問(wèn),所以無(wú)法通過(guò)第一種方式修改,一般的通過(guò)第二種方式修改私有屬性的值:定義一個(gè)可以調(diào)用的公有方法,在這個(gè)公有方法內(nèi)訪問(wèn)修改。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | # 定義一個(gè)Master父類(lèi)
class Master( object ):
def __init__( self ):
# 屬性
self .gufa = '古法煎餅果子配方'
# 方法
def make_cake( self ):
print ( '按照%s制作古法煎餅果子' % self .gufa)
def eat_master( self ):
print ( '在師傅家吃飯' )
# 定義一個(gè)School父類(lèi)
class School( object ):
def __init__( self ):
self .gufa = '現(xiàn)代煎餅果子配方'
def make_cake( self ):
print ( '按照%s制作現(xiàn)代煎餅果子' % self .gufa)
def eat_school( self ):
print ( '在學(xué)校吃飯' )
# 定義一個(gè)Prentice子類(lèi),繼承父類(lèi)Master,School
class Prentice(Master, School):
# 子類(lèi)重寫(xiě)了屬性和方法
def __init__( self ):
self .gufa = '貓式煎餅果子配方'
self .__money = 1000 # 億美金
# 返回私有屬性的值
def get_money( self ):
return self .__money
def set_money( self ,num):
self .__money = num
return num
def make_cake( self ):
print ( '用%s配方制作煎餅果子' % self .gufa)
# 獲取Master的屬性和方法
def make_master_cake( self ):
Master.__init__( self )
Master.make_cake( self )
# 獲取School 的屬性和方法
def make_school_cake( self ):
School.__init__( self )
School.make_cake( self )
# 新建一個(gè)大貓徒弟的類(lèi),繼承大貓類(lèi)Prentice
class PrenticePrentice(Prentice):
pass
# 創(chuàng)建大貓徒弟的實(shí)例對(duì)象
pp = PrenticePrentice()
print (pp.get_money())
# 可以通過(guò)訪問(wèn)公有方法set_money()來(lái)獲取私有屬性的值
pp.set_money( 2000 )
# 可以通過(guò)訪問(wèn)公有方法get_money()來(lái)修改私有屬性的值
print (pp.get_money())
|
多態(tài)大家應(yīng)該聽(tīng)說(shuō)過(guò)這樣的故事:有一個(gè)中醫(yī)世家,父親是當(dāng)?shù)匾晃环浅S忻睦洗蠓?看病看的非常好,兒子從小就跟著父親學(xué)醫(yī),醫(yī)術(shù)也不錯(cuò). 突然縣太爺家的千金生了重病,急需老大夫前去治病,但是老大夫又不在家,就請(qǐng)了老大夫的兒子前去給治病. 最后兒子也把病給治好了 那么,在python語(yǔ)言中能不能做類(lèi)似的事情,比如說(shuō) 在需要調(diào)用父類(lèi)對(duì)象方法的地方,我們也可以調(diào)用子類(lèi)對(duì)象的方法呢? 當(dāng)然可以! 要想這樣,我們需要使用接下來(lái)要學(xué)習(xí)的知識(shí)點(diǎn):多態(tài). 好,下面我們就開(kāi)始正式講解 多態(tài).在講解的時(shí)候: 1.先講解"多態(tài)"的概念 2.再講解如何使用多態(tài) 3.最后講解多態(tài)的好處 什么是多態(tài)?在需要使用父類(lèi)對(duì)象的地方,也可以使用子類(lèi)對(duì)象, 這種情況就叫多態(tài). 比如, 在函數(shù)中,我需要調(diào)用 某一個(gè)父類(lèi)對(duì)象的方法, 那么我們也可以在這個(gè)地方調(diào)用子類(lèi)對(duì)象的方法. 如何在程序中使用多態(tài)?可以按照以下幾個(gè)步驟來(lái)寫(xiě)代碼: 1.子類(lèi)繼承父類(lèi) 2.子類(lèi)重寫(xiě)父類(lèi)中的方法 3.通過(guò)對(duì)象調(diào)用這個(gè)方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | class Father( object ):
def cure( self ):
print ( '父親給人治病' )
class Son(Father):
# 重新cure方法
def cure( self ):
print ( '兒子給人治病' )
# 義函數(shù),在里面 調(diào)用醫(yī)生的cure函數(shù)
def call_cure(doctor):
# 調(diào)用醫(yī)生治病的方法
doctor.cure()
# 創(chuàng)建父類(lèi)對(duì)象
father = Father()
# 調(diào)用函數(shù),把父類(lèi)對(duì)象傳遞函數(shù)
call_cure(father)
# 創(chuàng)建子類(lèi)對(duì)象
son = Son()
# 調(diào)用函數(shù),把子類(lèi)對(duì)象傳遞函數(shù)
call_cure(son)
|
使用多態(tài)的好處 多態(tài)的好處:給call_cure(doctor)函數(shù)傳遞哪個(gè)對(duì)象,在它里面就會(huì)調(diào)用哪個(gè)對(duì)象的cure()方法,也就是說(shuō)在它里面既可以調(diào)用son對(duì)象的cure()方法,也能調(diào)用father對(duì)象的cure()方法,當(dāng)然了也可以在它里面調(diào)用Father類(lèi)其它子類(lèi)對(duì)象的cure()方法,這樣可以讓call_cure(doctor)函數(shù)變得更加靈活,額外增加了它的功能,提高了它的擴(kuò)展性. 類(lèi)屬性和實(shí)例屬性在了解了類(lèi)基本的東西之后,下面看一下python中這幾個(gè)概念的區(qū)別。 先來(lái)談一下類(lèi)屬性和實(shí)例屬性: 在前面的例子中我們接觸到的就是實(shí)例屬性(對(duì)象屬性),顧名思義,類(lèi)屬性就是類(lèi)對(duì)象所擁有的屬性,它被所有類(lèi)對(duì)象的實(shí)例對(duì)象所共有,在內(nèi)存中只存在一個(gè)副本,這個(gè)和C++中類(lèi)的靜態(tài)成員變量有點(diǎn)類(lèi)似。對(duì)于公有的類(lèi)屬性,在類(lèi)外可以通過(guò)類(lèi)對(duì)象和實(shí)例對(duì)象訪問(wèn) 1 2 3 4 5 6 7 8 9 10 | class People( object ):
name = 'Tom' # 公有的類(lèi)屬性
__age = 12 # 私有的類(lèi)屬性
p = People()
print (p.name) # 正確
print (People.name) # 正確
print (p.__age) # 錯(cuò)誤,不能在類(lèi)外通過(guò)實(shí)例對(duì)象訪問(wèn)私有的類(lèi)屬性
print (People.__age) # 錯(cuò)誤,不能在類(lèi)外通過(guò)類(lèi)對(duì)象訪問(wèn)私有的類(lèi)屬性
|
實(shí)例屬性(對(duì)象屬性)1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class People( object ):
address = '廣東' # 類(lèi)屬性
def __init__( self ):
self .name = 'xiaowang' # 實(shí)例屬性
self .age = 20 # 實(shí)例屬性
p = People()
p.age = 12 # 實(shí)例屬性
print (p.address) # 正確
print (p.name) # 正確
print (p.age) # 正確
print (People.address) # 正確,類(lèi)屬性
print (People.name) # 錯(cuò)誤,不是類(lèi)屬性
print (People.age) # 錯(cuò)誤,不是類(lèi)屬性
|
通過(guò)實(shí)例(對(duì)象)去修改類(lèi)屬性1 2 3 4 5 6 7 8 9 10 11 12 | class People( object ):
country = 'china' #類(lèi)屬性
print (People.country)
p = People()
print (p.country)
p.country = 'japan' # 增加一個(gè)跟類(lèi)屬性同名的實(shí)例屬性,就相當(dāng)于修改了類(lèi)屬性
print (p.country) # 實(shí)例屬性會(huì)屏蔽掉同名的類(lèi)屬性
print (People.country)
del p.country # 刪除實(shí)例屬性
print (p.country)
|
總結(jié):如果需要在類(lèi)外修改類(lèi)屬性,必須通過(guò)類(lèi)對(duì)象去引用然后進(jìn)行修改。如果通過(guò)實(shí)例對(duì)象去引用,會(huì)產(chǎn)生一個(gè)同名的實(shí)例屬性,這種方式修改的是實(shí)例屬性,不會(huì)影響到類(lèi)屬性,并且之后如果通過(guò)實(shí)例對(duì)象去引用該名稱的屬性,實(shí)例屬性會(huì)強(qiáng)制屏蔽掉類(lèi)屬性,即引用的是實(shí)例屬性,除非刪除了該實(shí)例屬性。 類(lèi)方法是類(lèi)對(duì)象所擁有的方法,需要用修飾器@classmethod來(lái)標(biāo)識(shí)其為類(lèi)方法,對(duì)于類(lèi)方法,第一個(gè)參數(shù)必須是類(lèi)對(duì)象,一般以cls作為第一個(gè)參數(shù)(當(dāng)然可以用其他名稱的變量作為其第一個(gè)參數(shù),但是大部分人都習(xí)慣以'cls'作為第一個(gè)參數(shù)的名字,就最好用'cls'了),能夠通過(guò)實(shí)例對(duì)象和類(lèi)對(duì)象去訪問(wèn)。 1 2 3 4 5 6 7 8 9 10 11 | class People( object ):
country = 'china'
#類(lèi)方法,用classmethod來(lái)進(jìn)行修飾
@ classmethod
def get_country( cls ):
return cls .country
p = People()
print (p.get_country()) #可以用過(guò)實(shí)例對(duì)象引用
print (People.get_country()) #可以通過(guò)類(lèi)對(duì)象引用
|
類(lèi)方法還有一個(gè)用途就是可以對(duì)類(lèi)屬性進(jìn)行修改: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | class People( object ):
country = 'china'
#類(lèi)方法,用classmethod來(lái)進(jìn)行修飾
@ classmethod
def get_country( cls ):
return cls .country
@ classmethod
def set_country( cls ,country):
cls .country = country
p = People()
print (p.get_country()) # china 可以用過(guò)實(shí)例對(duì)象訪問(wèn)
print (People.get_country()) # china 可以通過(guò)類(lèi)訪問(wèn)
p.set_country( 'japan' )
print (p.get_country()) # japan
print (People.get_country()) # japan
|
結(jié)果顯示在用類(lèi)方法對(duì)類(lèi)屬性修改之后,通過(guò)類(lèi)對(duì)象和實(shí)例對(duì)象訪問(wèn)都發(fā)生了改變 靜態(tài)方法需要通過(guò)修飾器@staticmethod來(lái)進(jìn)行修飾,靜態(tài)方法不需要多定義參數(shù),可以通過(guò)對(duì)象和類(lèi)來(lái)訪問(wèn)。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class People( object ):
country = 'china'
@ staticmethod
#靜態(tài)方法
def get_country():
return People.country
p = People()
# 通過(guò)對(duì)象訪問(wèn)靜態(tài)方法
print (p.get_country()) # china
# 通過(guò)類(lèi)訪問(wèn)靜態(tài)方法
print (People.get_country()) # china
|
總結(jié): 從類(lèi)方法和實(shí)例方法以及靜態(tài)方法的定義形式就可以看出來(lái),類(lèi)方法的第一個(gè)參數(shù)是類(lèi)對(duì)象cls,那么通過(guò)cls引用的必定是類(lèi)對(duì)象的屬性和方法; 實(shí)例方法的第一個(gè)參數(shù)是實(shí)例對(duì)象self,那么通過(guò)self引用的可能是類(lèi)屬性、也有可能是實(shí)例屬性(這個(gè)需要具體分析),不過(guò)在存在相同名稱的類(lèi)屬性和實(shí)例屬性的情況下,實(shí)例屬性優(yōu)先級(jí)更高。 靜態(tài)方法中不需要額外定義參數(shù),因此在靜態(tài)方法中引用類(lèi)屬性的話,必須通過(guò)類(lèi)實(shí)例對(duì)象來(lái)引用
最后修改:2020年3月2日 22:03
|