2020年9月16日星期三

[課後作業] 第041講:魔法方法:構造和析構|課後測試題及答案

[課後作業] 第041講:魔法方法:構造和析構|課後測試題及答案




《零基礎入門學習Python》視頻下載地址:傳送門?G5Dsb<[
HOSvR'GJ
測試題:來自:bbs.fishc.com 7W[P
(cPowered by bbs.fishc.com J;#4]8Q
0.是哪個特徵讓我們一眼就能認出這貨是魔法方法?dj'IUt!a
,0]Kfb)uN3
$K<U0f
1.類實例化對象所調用的第一個方法是什麼?so,Q>i S
C>J7d
-29iPowered by bbs.fishc.com F,
2.什麼時候我們需要在類中明確寫出__init__方法?GN6@w
A%Dzn~
B]@ZA2iW<}
3.請問下邊代碼存在什麼問題?ic_1kK


  1. class Test:
  2.         def __init__(self, x, y):
  3.                 return x + y
複製代碼

"'qEX
4.請問__new__方法是負責什麼任務?Qdjf6
來自:bbs.fishc.com J05<=rcHL
"@ScQo]來自:bbs.fishc.com
5. __del__魔法方法什麼時候會被自動調用?
msgP~:;>b,
<KEQ-t.
NO~G'j)
動動手:!c2bRK
],.tnY
0.小李做事常常丟三落四的,寫代碼也一樣,常常打開了文件又忘記關閉。你能不能寫一個FileObject類,給文件對象進行包裝,從而確認在刪除對象時文件能自動關閉?4"]Il0
NXa;e
.fg!J?*;
1.按照以下要求,定義一個類實現攝氏度到華氏度的轉換(轉換公式:華氏度=攝氏度*1.8+32)>!%y4
q版權屬於:bbs.fishc.com U8PC

要求:我們希望這個類盡量簡練地實現功能,如下P@yH2|sK
  1. >>> print(C2F(32))
  2. 89.6
複製代碼

f3^$~v
2.定義一個類繼承於int類型,並實現一個特殊功能:當傳入的參數是字符串的時候,返回該字符串中所有字符的ASCII碼的和(使用ord()獲得一個字符的ASCII碼值)。J%0}$"N'
K}來自:bbs.fishc.com [R(F
實現如下:,jOhEq2
  1. >>> print(Nint(123))
  2. 123
  3. >>> print(Nint(1.5))
  4. 1
  5. >>> print(Nint('A'))
  6. 65
  7. >>> print(Nint('FishC'))
  8. 461
複製代碼

c3.請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!:@S"_~JAK


回复您的答案即可查看參考答案! NS+;v版權屬於:bbs.fishc.com '
FbaK+OoZ
]do)8EVA
測試題答案:

本帖隱藏的內容

gAoE?
0.是哪個特徵讓我們一眼就能認出這貨是魔法方法?LO~wAT
Wms{)q[
答:魔法方法總是被雙下劃線包圍,例如__init__ <a{"Li[e
D><H4Jn1=
OgPFla
1.類實例化對象所調用的第一個方法是什麼?0sxV%
x8g-"K+v
答:__new__是在一個對象實例化的時候所調用的第一個方法。它跟其他魔法方法不同,它的第一個參數不是self而是這個類(cls),而其他的參數會直接傳遞給__init__方法的。來自:bbs.fishc.com Dqo]NBSj
ewyD來自:bbs.fishc.com ^uO
v7%*;}AY~
2.什麼時候我們需要在類中明確寫出__init__方法?g來自:bbs.fishc.com 2*Powered by bbs.fishc.com e34Z
W}t6<Uk
答:當我們的實例對象需要有明確的初始化步驟的時候,你可以在__init__方法中部署初始化的代碼。_6'ONgj#b$
PHU=Y}vbi
舉個例子:2iB78JYf
  1. # 我們定義一個矩形類,需要長和寬兩個參數,擁有計算周長和麵積兩個方法。
  2. # 我們需要對像在初始化的時候擁有“長”和“寬”兩個參數,因此我們需要重寫__init__方法
  3. # 因為我們說過,__init__方法是類在實例化成對象的時候首先會調用的一個方法,大家可以理解嗎?

  4. class Rectangle:
  5.         def __init__(self, x, y):
  6.                 self.x = x
  7.                 self.y = y
  8.         def getPeri(self):
  9.                 return (self.x + self.y) * 2
  10.         def getArea(self):
  11.                 return self.x * self.y

  12. >>> rect = Rectangle(3, 4)
  13. >>> rect.getPeri()
  14. 14
  15. >>> rect.getArea()
  16. 12
複製代碼

Rl版權屬於:bbs.fishc.com ~7jP.H
3.請問下邊代碼存在什麼問題?LoKPowered by bbs.fishc.com u
  1. class Test:
  2.         def __init__(self, x, y):
  3.                 return x + y
複製代碼

答:編程中需要主要到__init__方法的返回值一定是None,不能是其它!5@'(OaBmyY
;op<e>
qSJI>)*f$
4.請問__new__方法是負責什麼任務?X6$vQ3*z
Powered by bbs.fishc.com b,tH來自:bbs.fishc.com zr1
答:__new__方法主要任務時返回一個實例對象,通常是參數cls這個類的實例化對象,當然你也可以返回其他對象。RZ=e$
sCK Bp
!# eR9+[
5. __del__魔法方法什麼時候會被自動調用??C(8>=w
~yCGZ)v8
答:如果說__init__和__new__方法是對象的構造器的話,那麼Python也提供了一個析構器,叫做__del__方法。當對象將要被銷毀的時候,這個方法就會被調用。"9Dx}XV
^+2 ,{Z
但一定要注意的是,並非del x就相當於自動調用x.__del__(),__del__方法是當垃圾回收機制回收這個對象的時候調用的。IU版權屬於:bbs.fishc.com gE

U?'@S=`0
HyTd[rYL
動動手答案:]_7{C'M

本帖隱藏的內容

O60;I來自:bbs.fishc.com D[
0.小李做事常常丟三落四的,寫代碼也一樣,常常打開了文件又忘記關閉。你能不能寫一個FileObject類,給文件對象進行包裝,從而確認在刪除對象時文件能自動關閉?wOU+s.e3
#yON<$kCmP
答:只要靈活搭配__init__和__del__魔法方法,即可做到收放自如。?8L;PtiO
A*`,&:q%z
代碼清單:`S6F;=p
  1. class FileObject:
  2.     '''給文件對象進行包裝從而確認在刪除時文件流關閉'''

  3.     def __init__(self, filename='sample.txt'):
  4.         #讀寫模式打開一個文件
  5.         self.new_file = open(filename, 'r+')

  6.     def __del__(self):
  7.         self.new_file.close()
  8.         del self.new_file
複製代碼

8@來自:bbs.fishc.com hx
1.按照以下要求,定義一個類實現攝氏度到華氏度的轉換(轉換公式:華氏度=攝氏度*1.8+32)zcZ"1 8U
wJUojd80
要求:我們希望這個類盡量簡練地實現功能,如下j+rh -g
  1. >>> print(C2F(32))
  2. 89.6
複製代碼

答:為了盡量簡練地實現功能,我們採取了“偷龍轉鳳”的小技巧。在類進行初始化之前,通過“掉包” arg參數,讓實例對象直接返回計算後的結果。,C!R>*%
FJt?i
代碼清單:{S_E5e
  1. class C2F(float):
  2.         "攝氏度轉換為華氏度"
  3.         def __new__(cls, arg=0.0):
  4.                 return float.__new__(cls, arg * 1.8 + 32)
複製代碼

版權屬於:bbs.fishc.com 9 _x'h
2.定義一個類繼承於int類型,並實現一個特殊功能:當傳入的參數是字符串的時候,返回該字符串中所有字符的ASCII碼的和(使用ord()獲得一個字符的ASCII碼值)。Qdh~BOIS
P9p^)J1@,
實現如下:BIa?bi
  1. >>> print(Nint(123))
  2. 123
  3. >>> print(Nint(1.5))
  4. 1
  5. >>> print(Nint('A'))
  6. 65
  7. >>> print(Nint('FishC'))
  8. 461
複製代碼

代碼清單:|d){>D
  1. class Nint(int):
  2.         def __new__(cls, arg=0):
  3.                 if isinstance(arg, str):
  4.                         total = 0
  5.                         for each in arg:
  6.                                 total += ord(each)
  7.                         arg = total
  8.                 return int.__new__(cls, arg)
複製代碼

3.請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!

小甲魚希望你認真對待作業就像你希望小甲魚推出高質量視頻一樣渴望^_^


我們接下來幾節課的主要內容是魔法方法,此前我們已經接觸過Python中最常用的魔法方法__init__。

構造與析構

魔法方法總是被雙下劃線包圍,例如__init__
魔法方法是面向對象的Python的一切,如果你不知道魔法方法,說明你還沒能意識到面向對象的Python的強大
魔法方法的“魔力”體現在它們總能夠在適當的時候被自動調用
(1)__init__(self[ , ...])
它就相當於其它面向對象的編程語言的構造方法,也就是類在實例化對象時首先會調用的一個方法,在前面關於類的課程中,有人會問:“有時候在類定義時寫_ _init__方法,有時候卻沒有,這是為什麼呢?”
這是因為“需求”,因為我們有時候需要重寫__init__方法
我們在這裡定義一個矩形(Retangle)類:
  1. >>> class Retangle:
  2. def __init__(self, x, y):
  3. self.x = x
  4. self.y = y
  5. def getPeri(self):
  6. return(self.x + self.y) * 2
  7. def getArea(self):
  8. return self.x * self.y
  9. >>> rect = Retangle(3, 4)
  10. >>> rect.getPeri()
  11. 14
  12. >>> rect.getArea()
  13. 12
需要注意的是,__init__方法的返回值一定是None,不能試圖在__init__方法中返回一個什麼東西,以在實例化的時候返回給變量。
  1. >>> class A:
  2. def __init__(self):
  3. return "try return"
  4. >>> a = A()
  5. Traceback (most recent call last):
  6. File "<pyshell#18>", line 1, in <module>
  7. a = A()
  8. TypeError: __init__() should return None, not 'str'
一般我們在需要對一個對象進行初始化操作的時候,我們才會重寫__init__方法。
(2)__new__(cls[, ...])
其實__init__方法並不是實例化對象時第一個被調用的魔法方法,第一個被調用的應該是__new__(cls[, ...])方法,它跟其他的魔法方法不同,第一個參數不是self,而是class,它在init之前被調用,它後邊有參數的話,會原封不動的傳給__init__方法,new方法需要一個實例對像作為返回值,需要返回一個對象,通常是返回cls這個類的實例對象,也可以返回其它類的對象,需要說明的是,new方法平時是極少去重寫的,一般用Python默認的方案即可,但是用一種情況我們需要重寫new魔法方法,就是繼承一個不可變類型的時候,又需要進行些改的時候,那麼它的特性就顯得尤為重要了。
  1. >>> class CapStr(str):
  2. def __new__(cls, string):
  3. string = string.upper()
  4. return str.__new__(cls, string)
  5. >>> a = CapStr("I love fichc")
  6. >>> a
  7. 'I LOVE FICHC'
這裡繼承的父類str 是不可修改的,我們就不能在init中對其自身進行修改,所以我們就需要在new的時候進行一個替換,然用替換後的調用str的new方法做一個返回。如果這裡的new沒有做重寫的話,就會自動調用父類str的new。
(3)__del__(self)
如果我們說init和new方法是對象的構造器的話,那麼Python也提供了一個析構器,就是del方法,當對象需要被銷毀的時候,這個方法就會自動的被調用,但要注意的是,並非我們寫del x ,就會調用x.__del__(), del方法是當垃圾回收機制,我們知道Python有一個垃圾回收機制,當沒有任何變量去引用這個對象時,垃圾回收機制就會自動將其銷毀,這時候才會調用對象的del方法。
  1. >>> class C:
  2. def __init__(self):
  3. print("我是__init__方法,我被调用了")
  4. def __del__(self):
  5. print("我是__del__方法,我被调用了")
  6. >>> c1 = C()
  7. 我是__init__方法,我被调用了
  8. >>> c2 = c1
  9. >>> del c1
  10. >>> del c2
  11. 我是__del__方法,我被调用了
實例化的時候就會調用__init__方法,然後有c1 和c2 兩個變量指向這個對象,但並不是del c1 或者del c2 的時候就會調用__del__方法,而是當指向該對象的變量都被del的時候,才會被自動調用,來銷毀這個對象。

0 留言:

發佈留言