《從Python開始學(xué)編程》第4章 朝思暮想是對象

之前我們講了Python面向過程的一面吗蚌,現(xiàn)在我們來說說它面向?qū)ο蟮囊幻嫱纫校瑢W(xué)完這章你就會發(fā)現(xiàn),寫Python原來就是天天搞對象蚯妇,就連過程都是它的對象敷燎!那什么是面向?qū)ο蟮木幊棠兀覀兛梢院兔嫦蜻^程對比一下箩言。

舉個例子硬贯,我想吃奧利奧。從過程角度看陨收,我就要經(jīng)過扭一扭饭豹、舔一舔、泡一泡务漩、吃下去這幾個步驟才能完成吃奧利奧這個事情拄衰。從對象角度看(太詳細寫會占篇幅,這里會省略一些)饵骨,這件事參與者有手翘悉、奧利奧、舌頭居触、牛奶妖混、嘴包吝,那么首先我要得知這幾者的具體信息:手——有五個指頭,可以扭動源葫、奧利奧——一個帶餡兒的由兩個餅干構(gòu)成的夾心餅干......然后就是具體的做法了诗越,用兩只手的五指將夾心的奧利奧的兩片餅干扭動后,將兩片餅干分開息堂,餡兒會分別粘在兩個餅干上嚷狞,然后......

從這個例子我們可以發(fā)現(xiàn)幾個事情∪傺撸“扭一扭”等這些過程就好比一個個封裝好的函數(shù)床未,一個函數(shù)實現(xiàn)一個過程。但是可以看到振坚,無論哪個過程都會出現(xiàn)奧利奧這個東西薇搁,所以每個過程的關(guān)聯(lián)度很高,也即耦合性很強渡八。從對象的角度啃洋,每個角色都在做自己的動作,有自己的特點屎鳍,比如手做扭的動作宏娄,而奧利奧剛好是一個有兩個餅干的夾心,他們是完全分開的角色逮壁,所以面向?qū)ο蟮?strong>耦合性很弱孵坚。我們再看看面向?qū)ο罄锞唧w做法的描述,乍一看這不就是“扭一扭”的過程嘛窥淆。不過在看過廣告之前卖宠,一說“扭一扭”這個詞,大家肯定不知道是什么意思忧饭,因為這是對某一件事的高度抽象概括而來的幾個過程扛伍,只有仔細閱讀這個抽象的具體內(nèi)容,也就是看過廣告的眷昆,才知道“扭一扭”為何蜒秤。而這個抽象的具體內(nèi)容汁咏,是由一個個對象演繹而成的亚斋,所以說通過對象的描述,雖然復(fù)雜很多攘滩,但能夠?qū)嵲诘倪€原事物原本的過程帅刊。

所以綜上,面向?qū)ο蟮某绦蛘Z言是更加貼近人的語言漂问,而面向過程更貼近于機器赖瞒。在如今計算機性能大幅提高的今天女揭,我們越來越重視語言向人的方向發(fā)展,利用面向?qū)ο笳Z言栏饮,程序員可以更快更好的開發(fā)出新的產(chǎn)品吧兔,大大提高的應(yīng)用產(chǎn)能的發(fā)展。在對面向?qū)ο笥幸稽c了解后袍嬉,我們來學(xué)學(xué)Python面向?qū)ο蟮恼Z法境蔼。

1 給對象歸類

對象滿地球都是,什么《高等數(shù)學(xué)》伺通、貓箍土、老師......這么雜,我們首先要歸個類吧罐监,生物界還分七等呢吴藻,如果不分就沒有層次,事物看起來會很亂弓柱。比如天上這么多飛來飛去的沟堡,我們暫且歸為鳥類吧。那鳥都有什么呢矢空?比如怎么運動弦叶、吃什么、怎么吃妇多?我們來寫寫看:

class Bird():
    '''
    這是個鳥類
    '''
    move = 'fly'
    food = 'meat'
    def eat(self, name, thing):
        print(name,' eat a ',thing,' !')

class是“類”的關(guān)鍵字伤哺,Bird是我取的類的名字。里面就是鳥類的屬性了者祖,我們還是用三個單引號表示幫助文檔立莉,像move這類屬性稱為成員變量。利用def關(guān)鍵字七问,我們可以定義方法蜓耻,也就是這個類的一些動作,這里指鳥吃東西的動作械巡。這里的方法其實和函數(shù)差不多刹淌,括號里面是參數(shù)件余。唯一不同就是作為類的方法舔琅,括號內(nèi)必須有self關(guān)鍵字墙歪,是指“自己”鲫凶,也就是在方法里可以調(diào)用自己類的成員變量和方法岖免,具體調(diào)用后面講谈截。

其實Python有許多內(nèi)置方法嵌施,這些方法名字都用雙下劃線括起腿箩,我們這里講一個常用的方法挣磨,名為__init__()雇逞。這個方法的作用是荤懂,在你利用這個類創(chuàng)建一個對象時,它會立刻執(zhí)行塘砸,比如我們現(xiàn)在改寫一下鳥類:

class Bird(object):
    move = 'fly'
    food = 'meat'

    def __init__(self, name):
        self.name = name

    def eat(self, thing):
        print(self.name,' eat a ',thing,' !')

這個類現(xiàn)在新增加了init方法节仿,每創(chuàng)建一次對象,這個方法便會執(zhí)行掉蔬。創(chuàng)建方法在后面講解∷诔埽現(xiàn)在我們已經(jīng)創(chuàng)建了一個比較完整的鳥類,但這個類過于寬泛眉踱,鳥類名下有很多鳥挤忙,每個鳥有自己獨特的屬性,比如羽毛顏色會不一樣谈喳,這該怎么辦册烈?Python中,類可以繼承婿禽,繼承的類包含父類中所有的屬性赏僧,也會執(zhí)行父類的內(nèi)置方法,而且我們可以重寫父類扭倾,更改父類的方法淀零。比如我們現(xiàn)在創(chuàng)建天鵝類,天鵝也是鳥的一種呀膛壹。

class Swan(Bird):

    feather_color = 'white'  # 新的成員變量

    def eat(self):  # 重寫eat方法
        print('I ate a frog !')

天鵝類驾中,它繼承了鳥類的屬性外,我還添加了羽毛顏色模聋,并且重寫了吃的方法肩民。添加的屬性會在這一子類生效,而重寫的方法會代替父類的方法生效链方。我們還可以看到持痰,在定義鳥類時,括號寫的是object祟蚀,現(xiàn)在寫的是Bird工窍,可知括號內(nèi)寫的是繼承的類,object是對象類前酿,是所有類的總和患雏,也即是一個根類,一般第一個定義的就用object繼承薪者,而后面我們繼承鳥類纵苛,所以括號寫B(tài)ird剿涮。

2 我想要一個對象

女媧有了人的模型后捏了一堆的人從而創(chuàng)造了人類言津。我們現(xiàn)在“捏”了這么多類攻人,也該有自己的對象了。有了鳥類悬槽,現(xiàn)在就創(chuàng)建一只鳥吧怀吻,我們就叫他spring。

spring = Bird('spring')

看初婆,只需要一行代碼蓬坡,你就有一個對象了。原本只需要寫Bird()即可磅叛,但我們類里有一個init方法屑咳,這個方法里有一個name參數(shù),我們需要在這里寫入弊琴,執(zhí)行完該語句后兆龙,程序會立刻執(zhí)行init方法。在方法里敲董,我們使用了self.name紫皇,.是用于引用類屬性的,點前寫類的名字腋寨,后寫要調(diào)用的成員或方法即可聪铺。這里self是自己,也就是調(diào)用成員變量name并進行初始化萄窜。也即在執(zhí)行完這行代碼后铃剔,我們就有了name成員變量了。現(xiàn)在我們試試調(diào)用里面的屬性和方法:

print(spring.name, spring.move, spring.food)  # 調(diào)用成員變量
# 輸出: springflymeat
spring.eat('worm')  # 調(diào)用成員方法
# 輸出:spring eat a worm !

我們再造一只天鵝試試:

summer = Swam('summer')  # 創(chuàng)建對象
print(summer.name, summer.food, summer.feather_color)  # 調(diào)用成員變量
# 輸出:summermeatwhit
summer.eat  # 調(diào)用重寫方法
# 輸出:I ate a frog !

我們看到天鵝確實繼承了鳥類的屬性查刻,同時也按照重寫的eat方法輸出番宁。所以說,我們想要一個對象赖阻,要先有它的類蝶押,再通過類創(chuàng)造對象。我們可以調(diào)用對象的方法實現(xiàn)許多事情火欧。感興趣的可以試試把吃奧利奧的事情寫寫棋电。

3 一切皆對象

雖然說Python集成了面向過程、面向?qū)ο蟮扔谝簧淼某壵Z言苇侵,但究其本身赶盔,就是面向?qū)ο螅磺械难苌际抢脤ο髮懗龅挠芘āO日f說之前學(xué)到的幾種數(shù)據(jù)結(jié)構(gòu)于未,我曾提到它有很多的函數(shù)可以用,其實這些函數(shù)恰巧是處理這些數(shù)據(jù)的方法。Python把這些數(shù)據(jù)結(jié)構(gòu)看做對象烘浦,通過對象方法進行處理抖坪。我們加下來詳細說說處理他們的方法。

3.1 列表

list.count(5)       # 查看列表有幾個元素5
list.index(3)       # 查詢第一個出現(xiàn)3的元素下標
list.append(6)      # 在列表最后一個添加元素6
list.sort()         # 排序
list.reverse()      # 反轉(zhuǎn)次序
list.pop()          # 刪除最后一個元素并返回該元素
list. remove(2)     # 刪除第一個元素2
list. insert(0, 9)  # 在第0位置插入元素2
list. clear()       # 清空列表

3.2 元組和字符串

tuple.count(5)  # 查看元組有幾個元素5
tuple.index(3)  # 查詢元組第一個出現(xiàn)3的元素下標
str = 'hello world!'
sub = 'world'
str.count(sub)  # 返回sub在str出現(xiàn)的次數(shù)
str. find(sub) # 從左開始闷叉,返回找到第一個sub的第一個字符的位置擦俐,沒有返回-1
str. index(sub) # 從左開始,返回找到的第一個sub的索引握侧,沒有則報錯
str. rfind(sub) # 從右開始蚯瞧,返回找到第一個sub的第一個字符的位置,沒有返回-1
str. rindex(sub) # 從右開始品擎,返回找到的第一個sub的索引埋合,沒有則報錯
str. isalnum() # 查看是否所有字符都是字母或數(shù)字,是則返回True萄传,否則False
str. isalpha() # 查看是否所有字符都是字母饥悴,是則返回True,否則False
str. isdigit() # 查看是否所有字符都是數(shù)字盲再,是則返回True西设,否則False
str. istitle() # 查看是否所有字符都是首字母大寫,是則返回True答朋,否則False
str. isspace() # 查看是否所有字符都是空格贷揽,是則返回True,否則False
str. islower() # 查看是否所有字符都是梦碗,都是小寫禽绪,是則返回True,否則False
str. isupper() # 查看是否所有字符都是大寫洪规,是則返回True印屁,否則False
str. splite([sep, [max]]) # 以sep為分隔符分隔字符串max次,默認用空格斩例,都為選填
str. rsplite([sep, [max]]) # 從右開始分隔
str. join(s) # 返回以str分隔的s
str. strip([cub]) # 去掉字符串去掉開頭結(jié)尾的sub雄人,默認為空格
str. replace(sub, new_sub) # 用new_sub代替字符串中的sub
str. capitalize() # 返回開頭字母大寫的字符串
str. lower() # 返回所有字母小寫的字符串
str. upper() # 返回所有字母大寫的字符串
str. swapcase() # 返回大小寫全部反轉(zhuǎn)的字符串
str. title() # 將開頭字母全部大寫(以空格分開)
str. center(width) # 在width長度內(nèi)將字符串居中
str. ljust(width) # 在width長度內(nèi)將字符串居右
str. rjust(width) # 在width長度內(nèi)將字符串居左

3.3 詞典

dict.values()   # 返回詞典所有值(可用于循環(huán)遍歷)
dict.keys()     # 返回詞典所有鍵(可用于循環(huán)遍歷)
dict.clear()    # 清空詞典

不光是這些數(shù)據(jù)結(jié)構(gòu),就連面向過程的一些方法念赶,都是用面向?qū)ο髮崿F(xiàn)的础钠。

3.4 循環(huán)

每一個for循環(huán)都會自動尋找下一個變量的元素,事實上叉谜,它是通過迭代器和迭代器中的__next__()方法實現(xiàn)循環(huán)的旗吁,只是for循環(huán)就是運用這個原理,可以省略這樣的寫法停局。當next方法后已經(jīng)是末尾元素很钓,系統(tǒng)會返回StopIteration異常告知循環(huán)結(jié)束香府。我們可以嘗試利用面向?qū)ο蟮姆椒ㄖ苯訉崿F(xiàn)循環(huán):

list = [1, 2]
iterator = iter(list)  # iter是迭代器轉(zhuǎn)換函數(shù),可以將變量轉(zhuǎn)換成迭代器
iterator.next()
iterator.__next__()
iterator.__next__()  # 報錯

如果我們想從頭再次開始码倦,則需要重新定義一個迭代器企孩。上面的寫法其實可直接用for循環(huán)實現(xiàn):

for i in [1, 2]:

循環(huán)對象對于處理龐大數(shù)據(jù)的循環(huán)是有好處的,它可以邊遍歷叹洲,邊導(dǎo)入變量的元素柠硕,這樣可以讓計算機少占用內(nèi)存工禾。其實我們可以借助生成器實現(xiàn)自定義循環(huán)對象运提,可以一次性循環(huán)多種不同的元素。生成器是一個函數(shù)闻葵,用def關(guān)鍵字定義民泵,內(nèi)部每完成一種對象的定義就可以用yield關(guān)鍵字截斷一次,程序會對這個元素先做一次循環(huán)遍歷槽畔,再找下一個栈妆。舉個例子:

def gen():
    a = 100
    yield a
    a = a*8
    yield a
    yield 1000

for i in gen():
    print(i)

可以看到,for循環(huán)首先截斷在第一個a的元素并做一次循環(huán)厢钧,并用相同的方法進行后兩次循環(huán)相當于將數(shù)據(jù)分成3組循環(huán)鳞尔,在數(shù)據(jù)量龐大的情況下,可以節(jié)省內(nèi)存早直。

3.5 函數(shù)

函數(shù)也是一個對象寥假,事實上它是利用創(chuàng)建類里的__call__()方法實現(xiàn)的,我們可以看看:

class function(object):

def __call__(self, a)
    return a+5

其實這種寫法完全等價于:

def function(a):
    return a+5

只是后者本質(zhì)上還是調(diào)用前者的方法實現(xiàn)的霞扬,之后我們只需用正常的方法調(diào)用:

print(function(3))  # 輸出8

所以說Python的函數(shù)其實是使用面向?qū)ο蟮姆椒▽崿F(xiàn)的糕韧。

3.6 模塊和異常

我們之前講到許多調(diào)用函數(shù)的方法,包括自己定義的喻圃,以及Python庫萤彩。事實上他們也可以看做對象,所以這些庫又可以稱為模塊斧拍,我們是利用importfrom這兩個方法調(diào)用這些模塊雀扶。那么同理,異常也是對象肆汹,所以異常對象其實也有一些方法怕吴,下面舉例:

try:
    a = 1/0
except :
    ZeroDivisionError as e:
        print('catch ZeroDivisionError')
        print(e.message)

這里首先我們利用as關(guān)鍵字,將ZeroDivisionError這個錯誤名稱用e代替县踢,事實上這個在其他地方也可以用转绷。我們調(diào)用e對象的message方法,查看異常信息硼啤。

具體實例代碼可以看我的碼云:第四章樣例代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末议经,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌煞肾,老刑警劉巖咧织,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異籍救,居然都是意外死亡习绢,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門蝙昙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來闪萄,“玉大人,你說我怎么就攤上這事奇颠“苋ィ” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵烈拒,是天一觀的道長圆裕。 經(jīng)常有香客問我,道長荆几,這世上最難降的妖魔是什么吓妆? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮吨铸,結(jié)果婚禮上行拢,老公的妹妹穿的比我還像新娘。我一直安慰自己焊傅,他們只是感情好剂陡,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著狐胎,像睡著了一般鸭栖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上握巢,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天晕鹊,我揣著相機與錄音,去河邊找鬼暴浦。 笑死溅话,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的歌焦。 我是一名探鬼主播飞几,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼独撇!你這毒婦竟也來了屑墨?” 一聲冷哼從身側(cè)響起躁锁,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎卵史,沒想到半個月后战转,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡以躯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年槐秧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片忧设。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡刁标,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出见转,到底是詐尸還是另有隱情命雀,我是刑警寧澤蒜哀,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布斩箫,位于F島的核電站,受9級特大地震影響撵儿,放射性物質(zhì)發(fā)生泄漏乘客。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一淀歇、第九天 我趴在偏房一處隱蔽的房頂上張望易核。 院中可真熱鬧,春花似錦浪默、人聲如沸牡直。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽碰逸。三九已至,卻和暖如春阔加,著一層夾襖步出監(jiān)牢的瞬間饵史,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工胜榔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留胳喷,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓夭织,卻偏偏與公主長得像吭露,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子尊惰,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 本章是面對對象的編程范式讲竿。 1纬向、輕松看對象 “模擬”正是面向?qū)ο缶幊痰暮诵摹?類和對象提高了程序的可復(fù)用性,加強了...
    Guodw閱讀 231評論 0 0
  • 4.1 輕松看對象 1. 面向?qū)ο?前面第三章講到了Python面向過程的編程范式戴卜,即函數(shù)和模塊逾条,它們提高了程序的...
    塵濯閱讀 294評論 0 4
  • 4.1 輕松看對象 1.面向?qū)ο?關(guān)于面向?qū)ο蟮慕忉專篽ttp://www.reibang.com/p/7a5b...
    D系鼎溜閱讀 441評論 0 0
  • 一、對象 1.1 類和對象的作用 ①提高了程序的可復(fù)用性 ②加強了程序模擬真實世界的能力 Python的一條哲學(xué)理...
    大餅與我閱讀 590評論 0 1
  • 4.1 輕松看對象 除了面向過程的編程范式投剥,Python還支持面向?qū)ο蟮木幊谭妒健?2.類 把相近的東西歸為一類师脂,...
    XavieR_ZzQ閱讀 328評論 0 0