2020-07-22 Python學(xué)習(xí)筆記26 類和面向?qū)ο缶幊?/h2>

一些關(guān)于自己學(xué)習(xí)Python的經(jīng)歷的內(nèi)容,遇到的問(wèn)題和思考等,方便以后查詢和復(fù)習(xí)。

聲明:本人學(xué)習(xí)是在扇貝編程通過(guò)網(wǎng)絡(luò)學(xué)習(xí)的,相關(guān)的知識(shí)、案例來(lái)源于扇貝編程。如果使用請(qǐng)說(shuō)明來(lái)源。

第26關(guān):類和面向?qū)ο蟮木幊?/b>

練習(xí):中獎(jiǎng)號(hào)碼

模板代碼是彩票抽獎(jiǎng)機(jī)的代碼,使用的是 面向過(guò)程 的思維方式寫的,思考一下用 面向?qū)ο?的思維如何改寫?寫完記得查看答案對(duì)比一下哦~

#from random import randint

#times = 6

#lottery = []

#for i in range(0, times):

#? number = randint(0, 99)

#? lottery.append(number)

#print('本期彩票中獎(jiǎng)號(hào)碼為:%s' % lottery)

#面向?qū)ο?/p>

from random import randint

# 由于需要隨機(jī)產(chǎn)生的數(shù)字,所以導(dǎo)入隨機(jī)生成函數(shù)是必須的。

class Lottery:? #定義一個(gè)類,這個(gè)我想到了,但是忘記了類的名稱首字母要大寫的要求了

? def __init__(self, times):? #定義一個(gè)初始化,參數(shù)處理self,還有一個(gè)是抽獎(jiǎng)次數(shù)。

? ? self.times = times? #設(shè)置初始化的特征

? ? self.lottery = []? # 設(shè)置一個(gè)空列表,因?yàn)槭浅跏蓟卣鳎郧懊婕觽€(gè)self

? def draw_lottery(self):? # 定義一個(gè)抽獎(jiǎng)的方法/行為

? ? for i in range(0, self.times):? #用for循環(huán),來(lái)個(gè)遍歷,只是范圍末端是一個(gè)參數(shù)

? ? ? number = randint(0, 99)

? ? ? self.lottery.append(number)

? def print_lottery(self):? ? # 定義一個(gè)打印結(jié)果的方法/行為

? ? print('本期彩票中獎(jiǎng)號(hào)碼為:%s' % self.lottery)


lottery = Lottery(6)? #實(shí)例化,同時(shí)對(duì)times賦值


lottery.draw_lottery()? # 調(diào)用實(shí)例化后的抽獎(jiǎng)方法


lottery.print_lottery()? #調(diào)用打印抽獎(jiǎng)結(jié)果的方法

說(shuō)實(shí)話,我是沒(méi)有弄出來(lái),通過(guò)前面的例子,我知道面向?qū)ο蟮淖兂伤悸肥侨齻€(gè)部分:第一個(gè)是定義一個(gè)類,第二個(gè)是實(shí)例化,第三個(gè)是調(diào)用。其中后兩個(gè)比較簡(jiǎn)單,第一個(gè)是比較難的。我看了前面那個(gè)關(guān)于學(xué)生姓名和成績(jī)的例子,但是我還是沒(méi)有思路如何做。

原因是前面學(xué)生成績(jī)的例子是個(gè)靜態(tài)的,就是資料時(shí)固定的,不變的。而這個(gè)是動(dòng)態(tài)的,號(hào)碼是沒(méi)有的。所以如何用定義類的方式來(lái)解決呢。我沒(méi)有思路,沒(méi)有辦法。只好看了答案。

發(fā)現(xiàn):三個(gè)步驟是找到了,第一個(gè)步驟是重點(diǎn),而且第一個(gè)步驟中就是抽即將的過(guò)程,所以這個(gè)步驟是對(duì)象中包含過(guò)程的,把整個(gè)抽獎(jiǎng)過(guò)程作為一個(gè)對(duì)象。

練習(xí):kakarotto

賽亞人會(huì)在月圓之夜因?yàn)樵铝涟l(fā)射出來(lái)的布爾茲光,進(jìn)化成巨猿。變身后是常態(tài)的 10 倍左右,并且會(huì)失去理智。

假設(shè)現(xiàn)在是月圓之夜,請(qǐng)你在類實(shí)例化時(shí)自動(dòng)調(diào)用 transform() 方法變身,并添加 __str__() 方法返回 我是來(lái)自xxx的xxx,代碼最終運(yùn)行結(jié)果應(yīng)如下:

變身巨猿

我是來(lái)自貝吉塔行星的卡卡羅特

要求:

給 Saiyan 類添加初始化方法,初始化方法接受 name 參數(shù)用于初始化 self.name,并調(diào)用 transform() 方法;

給 Saiyan 類添加 __str__() 方法,使打印 Saiyan 類的實(shí)例 kakarotto 時(shí)結(jié)果為 我是來(lái)自貝吉塔行星的卡卡羅特。

class Saiyan:

? def __init__(self, name):

? ? self.name = name


? ? self.born_place = '貝吉塔行星'

self.character = '天生好戰(zhàn)性格暴躁'?

#這兩個(gè)沒(méi)有賦值,還是特征,答案是放在外面的,我也考慮了這一點(diǎn),放在初始化外面更合理。放在這里前面加self,放在初始化外面,前面則不用加self

這兩個(gè)應(yīng)該也是賦值了,只不過(guò)似乎固定的值,而不是一個(gè)變量。

? def transform(self):

? ? print('變身巨猿')

? def __str__(self):

? ? return('我是來(lái)自%s的%s'%(self.born_place, self.name))


kakarotto = Saiyan('卡卡羅特')

kakarotto.transform() #答案是在初始化中調(diào)用這個(gè)方法的,所以最后就沒(méi)有了,符合題意

print(kakarotto)

變身巨猿

我是來(lái)自貝吉塔行星的卡卡羅特


根據(jù)答案更改之后的結(jié)果:

class Saiyan:

? born_place = '貝吉塔行星'

? character = '天生好戰(zhàn)性格暴躁'? #不在初始化中,所以前面不能再加self

? def __init__(self, name):

? ? self.name = name

? ? self.transform()? #可以在初始化中賦值,可以調(diào)用方法



? def __str__(self):

? ? return('我是來(lái)自%s的%s'%(self.born_place, self.name))

? def transform(self):

? ? print('變身巨猿')


kakarotto = Saiyan('卡卡羅特')

#kakarotto.transform()

print(kakarotto)

也可以這樣修改:

class Saiyan:


? def __init__(self, name, born_place, character):? 四個(gè)參數(shù)

? ? self.name = name

? ? self.transform()

? ? self.born_place = born_place

? ? self.character = character? 所有參數(shù)都進(jìn)行了初始化


? def __str__(self):

? ? return('我是來(lái)自%s的%s,%s'%(self.born_place, self.name, self.character))

? def transform(self):

? ? print('變身巨猿')


kakarotto = Saiyan('李建升','地球','天生愛(ài)吃肉')

#kakarotto.transform()

print(kakarotto)

變身巨猿

我是來(lái)自地球的李建升,天生愛(ài)吃肉

kakarotto = Saiyan('卡卡羅特','貝吉塔行星','天生天生好戰(zhàn)性格暴躁')

#kakarotto.transform()

print(kakarotto)

變身巨猿

我是來(lái)自貝吉塔行星的卡卡羅特,天生天生好戰(zhàn)性格暴躁

練習(xí):三頭六臂的哪吒

哪吒會(huì) 三頭六臂 的法術(shù),我們來(lái)給模板代碼中的類補(bǔ)充一個(gè)初始化方法,使其打印出 我叫哪吒,我有 3 頭 6 臂。

class Human:

? # 在這里補(bǔ)充初始化方法

? def __init__(self, name, heads, arms):

? ? self.name = name

? ? self.heads = heads

? ? self.arms = arms


? def intro(self):

? ? print('我叫{},我有{}頭{}臂'.format(self.name, self.heads, self.arms))

nezha = Human('哪吒', 3, 6)

nezha.intro()

練習(xí):三頭六臂的哪吒 另一個(gè)答案:

我們通過(guò) intro() 方法打印出了 我叫哪吒,我有 3 頭 6 臂。接下來(lái)我們?nèi)サ?intro() 方法,使用神奇方法 __str__() 來(lái)打印 我叫哪吒,我有 3 頭 6 臂。

class Human:

? def __init__(self, name, heads, arms):

? ? self.name = name

? ? self.heads = heads

? ? self.arms = arms

? def __str__(self):

? ? return '我叫{},我有{}頭{}臂'.format(self.name, self.heads, self.arms)

? #def intro(self):

? # print('我叫{},我有{}頭{}臂'.format(self.name, self.heads, self.arms))

nezha = Human('哪吒', 3, 6)

#nezha.intro()

print(nezha)

學(xué)習(xí)筆記:

初始化方法

在 Python 的類中,有一種特殊的方法——初始化方法。它的格式是 def __init__(self):,方法名由 init(initialize 的縮寫,初始化的意思)加左右兩邊的 雙下劃線 組成。

注意:初始化方法的 init 前后有 兩個(gè) 下劃線。

初始化方法的特殊之處是:每當(dāng)進(jìn)行類的實(shí)例化時(shí),初始化方法會(huì)自動(dòng)被執(zhí)行。

只是創(chuàng)建了實(shí)例,并沒(méi)有調(diào)用 __init__ 方法,它自己就自動(dòng)執(zhí)行了。利用這個(gè)特性,我們通常會(huì)在 初始化方法 里完成類屬性初始值的設(shè)置。

除了進(jìn)行固定的初始值設(shè)置,初始化方法 可以接收其他參數(shù),進(jìn)行自定義的屬性初始值設(shè)置。

class Human:

? def __init__(self, name, arms, legs, hair):

? ? # self.不能丟

? ? self.name = name

? ? self.arms = arms

? ? self.legs = legs

? ? self.hair = hair

? def walk(self):

? ? print('直立行走')

? def speak(self):

? ? print('說(shuō)著各式各樣的語(yǔ)言')

? def intro(self):

? ? print('我叫{},我有{}'.format(self.name, self.hair))

xiaobei = Human('小貝', 2, 2, '粉紅色的頭發(fā)')

print(xiaobei.name)

# 輸出:小貝

xiaobei.intro()

# 輸出:我叫小貝,我有粉紅色的頭發(fā)

給 初始化方法 額外添加了 4 個(gè)參數(shù),因此在實(shí)例化的時(shí)候要傳入對(duì)應(yīng)的值。Human('小貝', 2, 2, '粉紅色的頭發(fā)') 這里的 '小貝' 賦值給 self.name,兩個(gè) 2 分別賦值給 self.arms 和 self.legs,'粉紅色的頭發(fā)' 賦值給 self.hair。

當(dāng)實(shí)例化完成之后,初始化方法會(huì)自動(dòng)執(zhí)行,這樣我們就完成了自定義的屬性初始值設(shè)置。然后我們可以通過(guò) 實(shí)例名.屬性名 在類外訪問(wèn)或 self.屬性名 在類的方法中訪問(wèn)了。

神奇方法

像 __init__() 這樣的方法在 Python 的類中被稱為 神奇方法(或魔術(shù)方法),它們的特征是被 雙下劃線 所包裹。這一節(jié)中我們?cè)俳榻B一個(gè)神奇方法——__str__()。

class Human:

? arms = 2

? legs = 2

? hair = '各種顏色的頭發(fā)'

? def walk(self):

? ? print('直立行走')

? def speak(self):

? ? print('說(shuō)著各式各樣的語(yǔ)言')

? def intro(self):

? ? print('人類有%d條胳膊%d條腿' % (self.arms, self.legs))

# 類的實(shí)例化

human = Human()

human.intro()

# 輸出:人類有2條胳膊2條腿

class Human:

? arms = 2

? legs = 2

? hair = '各種顏色的頭發(fā)'

? def __str__(self):

? ? return '人類有%d條胳膊%d條腿' % (self.arms, self.legs)

? def walk(self):

? ? print('直立行走')

? def speak(self):

? ? print('說(shuō)著各式各樣的語(yǔ)言')

human = Human()

print(human)

# 輸出:人類有2條胳膊2條腿

可以看到,有了 __str__() 方法,直接打印實(shí)例的結(jié)果為 __str__() 方法的返回值。因此,我們可以使用 __str__() 方法來(lái)描述一個(gè)類。

面向?qū)ο笈c面向過(guò)程

與 面向?qū)ο?相對(duì)應(yīng)的是 面向過(guò)程,我們之前寫代碼都用的是 面向過(guò)程 的思維方式。也就是把一個(gè)問(wèn)題拆分成一個(gè)個(gè)步驟,然后用函數(shù)實(shí)現(xiàn)各個(gè)步驟,依次調(diào)用解決問(wèn)題。

而 面向?qū)ο?的思維方式是:把一個(gè)問(wèn)題拆分成各個(gè)對(duì)象,建立對(duì)象的目的不是為了完成一個(gè)步驟,而是為了描述某個(gè)事物在整個(gè)解決問(wèn)題的步驟中的行為和特征(方法和屬性)

可以看到,面向過(guò)程 是以動(dòng)作(函數(shù))為主體,對(duì)象(這個(gè)例子里是學(xué)生)作為參數(shù)傳遞給函數(shù)。而 面向?qū)ο?是以對(duì)象為主體,動(dòng)作和特征分別是對(duì)象的方法和屬性。用代碼來(lái)描述就是,面向過(guò)程:動(dòng)作(對(duì)象);面向?qū)ο螅簩?duì)象.動(dòng)作()。

使用 面向?qū)ο?的思維方式的好處是:程序的可讀性、可拓展性、可維護(hù)性高。但并不是說(shuō) 面向過(guò)程 就一無(wú)是處了,二者相輔相成,并不是對(duì)立的,我們要根據(jù)實(shí)際情況選擇合適的編程思維方式。


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容