2020年9月17日星期四

[課後作業] 第050講:模塊:模塊就是程序|課後測試題及答案

[課後作業] 第050講:模塊:模塊就是程序|課後測試題及答案




《零基礎入門學習Python》視頻下載地址:傳送門
Ch<0Y)Z&rq_2vDn5Q,pR+iW
測試題(筆試,不能上機哦~):
NSdg%Ms)v2@] mc54&+ |!O?[p
0.說到底,Python的模塊是什麼?kOnI-
CRlN&Kn1Vm=4B{(EY'2*,oyG"%`:;
5q0&>r3Ef8d(6p.U=~N!$a`-ZJ_S
1.我們現在有一個hello.py的文件,裡邊有一個hi ()函數:
.&ymiM?t

  1. def hi():
  2.     print("Hi everyone, I love FishC.com!")
複製代碼

請問我如何在另外一個源文件test.py裡邊使用hello.py的hi()函數呢?6SELR)<soK
(,h+VNcU|P %q#JrCA1g
hbgy Mvp71u|?F,98tdfqm;&:0
2.你知道的總共有幾種導入模塊的方法?A1Ry%iW#
rG[]}DI* g&!t%{oE#kx?NO
{Vw7 `qZ_2.'l60E;o)<?r-mR"
3.曾經我們講過有辦法阻止from…import *導入你的“私隱”屬性,你還記得是怎麼做的嗎?wcqZ:
8"tF9'){O3zlTy&,n[@h
yP3S"NhC4Fl_|zXfG-%grv5Z
4.倘若有a.py和b.py兩個文件,內容如下:
AR:K "Cb#c{
  1. # a.py
  2. def sayHi():
  3.     print("嗨,我是A 模塊~")

  4. # b.py
  5. def sayHi():
  6.     print("嗨,我是B 模塊~")
複製代碼

那麼我在test.py文件中執行以下操作,會打印什麼結果?fylWVaD0M
  1. # test.py
  2. from a import sayHi
  3. from b import sayHi

  4. sayHi()
複製代碼

O10Di,7 +Q&b:KeuN;rhz>
5.執行下邊a.py或b.py任何一個文件,都會報錯,請嘗試解釋一下此現象。Rt8k=ZDq
  1. # a.py
  2. from b import y
  3. def x():
  4.     print('x')

  5. # b.py
  6. from a import x
  7. def y():
  8.     print('y')

  9. >>>
  10. Traceback (most recent call last):
  11.   File "/Users/FishC/Desktop/a.py", line 1, in <module>
  12.     from b import x
  13.   File "/Users/FishC/Desktop/b.py", line 1, in <module>
  14.     import a
  15.   File "/Users/FishC/Desktop/a.py", line 1, in <module>
  16.     from b import x
  17. ImportError: cannot import name 'x'
複製代碼

5T7a-CBZ&24m~srF]9e",NiL InR1
動動手(一定要自己動手試試哦~):kwh9E+1
"},elCI'~F<+@tn2vyGBhm7q8>p
0.問大家一個問題:Python支持常量嗎?相信很多魚油的答案都是否定的,但實際上Python內建的命名空間是支持一小部分常量的,比如我們熟悉的True,False,None等,只是Python沒有提供定義常量的直接方式而已。那麼這一題的要求是創建一個const模塊,功能是讓Python支持常量。$JSz{md'LD
o30g^$;!H]5Z}D'Id.t:X[W+O1
說到這里大家可能還是一頭霧水,沒關係,我們舉個栗子。fYZ^pVw=
r>nhI.&#i?MzWyR_d:fE,2JFC9TbU
test.py是我們的測試代碼,內容如下:&m%c1>
  1. # const 模塊就是這道題要求我們自己寫的
  2. # const 模塊用於讓Python 支持常量操作
  3. import const

  4. const.NAME = "FishC"
  5. print(const.NAME)

  6. try:
  7.     # 嘗試修改常量
  8.     const.NAME = "FishC.com"
  9. except TypeError as Err:
  10.     print(Err)

  11. try:
  12.     # 變量名需要大寫
  13.     const.name = "FishC"
  14. except TypeError as Err:
  15.     print(Err)
複製代碼

執行後的結果是:版權屬於:bbs.fishc.com
  1. >>>
  2. FishC
  3. 常量無法改變!
  4. 常量名必須由大寫字母組成!
複製代碼

在const模塊中我們到底做了什麼,使得這個模塊這麼有“魔力”呢?大家跟著小甲魚的提示,一步步來做你就懂了:ZB,2N@Q
fg.Mwe]OVhd2P!Wy@Uoj9)rQ3A
  • 提示一:我們需要一個Const 類
  • 提示二:重寫Const 類的某一個魔法方法,指定當實例對象的屬性被修改時的行為
  • 提示三:檢查該屬性是否已存在
  • 提示四:檢查該屬性的名字是否為大寫
  • 提示五:細心的魚油可能發現了,怎麼我們這個const 模塊導入之後就把它當對象來使用(const.NAME = "FishC")了呢?難道模塊也可以是一個對象?沒錯啦,在Python 中無處不對象,到處都是你的對象。使用以下方法可以將你的模塊與類A 的對象掛鉤。

  1. '''
  2. sys.modules 是一個字典,它包含了從Python 開始運行起,被導入的所有模塊。鍵就是模塊名,值就是模塊對象。
  3. '''
  4. import sys
  5. sys.modules[__name__] = A()
複製代碼

呃……好像說得有點太多了,大家一定要自己動手先嘗試完成哦~ >]'H?3581
O2][JX*1j`gnPB>0WF!?
請務必自己先動手,貪一時之快先看答案,您將失去一次鍛煉的機會。t~U>1#T)1.請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!xjC1<-rRJ6sQ:"UqD9'Tc#|Z[A>Mf

回复您的答案即可查看參考答案! '68;j4L
TcEJCUtm4`=GLWRg_2*|ewQu&
測試題答案:Powered by bbs.fishc.com

本帖隱藏的內容

0.說到底,Python的模塊是什麼?KS5C(>
.4@DT<%f&U`]dlej^oywauI"
答:模塊就是程序。沒錯,所謂模塊就是平時我們寫的任何代碼,然後保存的每一個“.py”結尾的文件,都是一個獨立的模塊。v!uwa
X I.0>$uM~Hl!tF:#<h3SmzJ52odW
_tSdM=(T+pah|,@f]G:FW
1.我們現在有一個hello.py的文件,裡邊有一個hi()函數:RCXGg_.fa
  1. def hi():
  2.     print("Hi everyone, I love FishC.com!")
複製代碼

請問我如何在另外一個源文件test.py裡邊使用hello.py的hi()函數呢?(Xg+,])
.9}R1dTqMOiJ;E^h+Ua k&=KPe
答:只需要在test.py中導入hello模塊(文件名=模塊名)即可使用hello.py中的hi()函數。imr:wYc<U
Qj#W3DE<U)pTqC9,xmgf'~r_1vb2K
EGO"kz'J_?;c2V=oQ18~:MBnPsj}e
2.你知道的總共有幾種導入模塊的方法?swTiF
MA1i$tly&bh !6:Sd|{Gpa'4X7
答:我們總共介紹了三種導入模塊的方法。版權屬於:bbs.fishc.com
9MXGPr.*>WtF`eQ7^aEj1C;{m
第一種:import模塊名來自:bbs.fishc.com
第二種:from模塊名import函數名8<tMm2w
第三種:import模塊名as新名字5&HNe
CtW5*OvK$BUpR9fEn?Dq
0WpU+")Kz]^@P3$Na&teguj|r4Z~
3. 曾經我們講過有辦法阻止from…import * 導入你的“私隱”屬性,你還記得是怎麼做的嗎?5K{bCDe~gL
*L0^QY@yPZAEq:KsuOp<J;v }=z9`
答:如果你不想模塊中的某個屬性被from…import *導入,那麼你可以給你不想導入的屬性名稱的前邊加上一個下劃線(_)。不過需要注意的是,如果使用import …導入整個模塊,或者顯式地使用import xx._oo導入某個屬性,那麼這個隱藏的方法就不起作用了。
3soWwmD~*^e,LrRc;K[l4
N|b8ip;1W>[,dU_{XKx`#'Y
4.倘若有a.py和b.py兩個文件,內容如下:RG9"}wQ
  1. # a.py
  2. def sayHi():
  3.     print("嗨,我是A 模塊~")

  4. # b.py
  5. def sayHi():
  6.     print("嗨,我是B 模塊~")
複製代碼

那麼我在test.py文件中執行以下操作,會打印什麼結果?'aQgL~yI8
  1. # test.py
  2. from a import sayHi
  3. from b import sayHi

  4. sayHi()
複製代碼

答:會打印“嗨,我是B模塊~”,因為第二次導入的b模塊把a模塊的同名函數sayHi()給覆蓋了,這就是所謂命名空間的衝突。所以,在項目中,特別是大型項目中我們應該避免使用from…import...,除非你非常明確不會造成命名衝突。^s>ym
>P:eNWzfU)%~ZXvQ`y6'
>XSv<}[j'Q&B,F6p12|lWt:zY
5.執行下邊a.py或b.py任何一個文件,都會報錯,請嘗試解釋一下此現象。|sqYi2d'
  1. # a.py
  2. from b import y
  3. def x():
  4.     print('x')

  5. # b.py
  6. from a import x
  7. def y():
  8.     print('y')

  9. >>>
  10. Traceback (most recent call last):
  11.   File "/Users/FishC/Desktop/a.py", line 1, in <module>
  12.     from b import x
  13.   File "/Users/FishC/Desktop/b.py", line 1, in <module>
  14.     import a
  15.   File "/Users/FishC/Desktop/a.py", line 1, in <module>
  16.     from b import x
  17. ImportError: cannot import name 'x'
複製代碼

答:這個是循環嵌套導入問題。無論運行a.py或b.py哪一個文件都會拋出ImportError異常。這是因為在執行其中某一個文件(a.py)的加載過程中,會創建模塊對象並執行對應的字節碼。但當執行第一個語句的時候需要導入另一個文件(from b import y),因此CPU會轉而去加載另一個文件(b.py)。同理,執行另一個文件的第一個語句(from a import x)恰好也是需要導入之前的文件(a.py)。此時,之前的文件處於僅導入第一條語句的階段,因此其對應的字典中並不存在x,故拋出“ImportError: cannot import name 'x'”異常。]~@u!s
y1>{K$&=0I!X-Y'6wEc~GH
解決方案是直接使用import語句導入:tnfj+?Qh
  1. # a.py
  2. import b

  3. def x():
  4. print('x')

  5. # b.py
  6. import a

  7. def y():
  8.     print('y')

  9. ax()
複製代碼

來自:bbs.fishc.com
EKWY]laog7_9"NHnQ:kxR;1|'h%?B
動動手答案:Powered by bbs.fishc.com

本帖隱藏的內容

Powered by bbs.fishc.com
0.問大家一個問題:Python支持常量嗎?相信很多魚油的答案都是否定的,但實際上Python內建的命名空間是支持一小部分常量的,比如我們熟悉的True,False,None等,只是Python沒有提供定義常量的直接方式而已。那麼這一題的要求是創建一個const模塊,功能是讓Python支持常量。CYP%5hbR{
no+k:z3~RM07I"ZGSLmbwguK|NV;y
說到這里大家可能還是一頭霧水,沒關係,我們舉個栗子。:wFr`uk
V^%jmWX0zaTP&LF,o+Jqk*$
test. py是我們的測試代碼,內容如下:>$TfOyl0
  1. # const 模塊就是這道題要求我們自己寫的
  2. # const 模塊用於讓Python 支持常量操作
  3. import const

  4. const.NAME = "FishC"
  5. print(const.NAME)

  6. try:
  7.     # 嘗試修改常量
  8.     const.NAME = "FishC.com"
  9. except TypeError as Err:
  10.     print(Err)

  11. try:
  12.     # 變量名需要大寫
  13.     const.name = "FishC"
  14. except TypeError as Err:
  15.     print(Err)
複製代碼

執行後的結果是:版權屬於:bbs.fishc.com
  1. >>>
  2. FishC
  3. 常量無法改變!
  4. 常量名必須由大寫字母組成!
複製代碼

在const模塊中我們到底做了什麼,使得這個模塊這麼有“魔力”呢?大家跟著小甲魚的提示,一步步來做你就懂了:'AL^`vsa
2e:<=mLM^(PH$4>uN-1Fo%!pxnJ
  • 提示一:我們需要一個Const 類
  • 提示二:重寫Const 類的某一個魔法方法,指定當實例對象的屬性被修改時的行為
  • 提示三:檢查該屬性是否已存在
  • 提示四:檢查該屬性的名字是否為大寫
  • 提示五:細心的魚油可能發現了,怎麼我們這個const 模塊導入之後就把它當對象來使用(const.NAME = "FishC")了呢?難道模塊也可以是一個對象?沒錯啦,在Python 中無處不對象,到處都是你的對象。使用以下方法可以將你的模塊與類A 的對象掛鉤。

  1. '''
  2. sys.modules 是一個字典,它包含了從Python 開始運行起,被導入的所有模塊。鍵就是模塊名,值就是模塊對象。
  3. '''
  4. import sys
  5. sys.modules[__name__] = A()
複製代碼

呃……好像說得有點太多了,大家一定要自己動手先嘗試完成哦~ >UAJ41
4e%7tDwmO@T+EaWk|~co>'M
代碼清單:Powered by bbs.fishc.com
  1. # 該模塊用於讓Python 支持常量操作
  2. class Const:   
  3.     def __setattr__(self, name, value):
  4.         if name in self.__dict__:
  5.             raise TypeError('常量無法改變!')
  6.             
  7.         if not name.isupper():
  8.             raise TypeError('常量名必須由大寫字母組成!')

  9.         self.__dict__[name] = value

  10. import sys
  11. sys.modules[__name__] = Const()
複製代碼

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

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

這一講將給大家介紹一個新的知識:模塊。
(一)什麼是模塊?
模塊是更高級的封裝,說到封裝,回顧一下我們之前學過哪些封裝:
  • 容器 - > 數據的封裝
  • 函數 - > 語句的封裝
  • 類 - > 方法和屬性的封裝
  • 模塊 - > 模塊就是程序
沒錯,模塊就是平常我們寫的任何代碼,保存每一個.py 結尾的Python文件,就是保存了一個獨立的模塊。我們來句一個簡單的例子:
我們在安裝Python的目錄下新建一個hello.py文件,我們在裡面定義一個hi()函數,當我按下Ctrl + S將這個文件保存起來的時候,這就是一個獨立的Python模塊了,大家要注意的是,為了使我們的IDLE能夠順利的找到這個模塊,我們這個模塊的位置應該跟我們調用的程序在同一個文件夾下(注:關於從任何文件夾導入模塊的方法,請參閱-> Python如何從任何文件夾導入模塊
  1. def hi():
  2. print('Hi, everyone!')
我們在IDLE裡調用該模塊:
>>> import hello
既然沒有報錯,就說明導入模塊成功了,我們試著調用一下hello 模塊中的hi() 函數:
  1. >>> hi()
  2. Traceback (most recent call last):
  3. File "<pyshell#10>", line 1, in <module>
  4. hi()
  5. NameError: name 'hi' is not defined
出錯了,這是為什麼呢?從報錯信息,我們可以知道錯誤的根源是Python找不到hi()這個函數。為什麼會這樣呢?我們明明在hello.py文件中定義了hi()函數啊,其實這個問題跟我們這個命名空間這個概念有關。我們先來講講命名空間這個概念,你就知道問題所在了。那什麼是命名空間呢?其實很好理解,我來講個例子:
假如你們班有個叫小花的女孩,長得像個花瓶一樣的漂亮,於是,你趁著2月14情人節這天,買通了學校廣播站的同學,讓他幫你播放愛的宣言,並約定於學校附近的XX賓館OO房間等著她,但是呢,你意想不到的是,另一個班級恰好也有一個叫做小花的姑娘,長得略微驚悚,後邊的劇情大家可以自行腦補了哈。
上邊這個悲涼的故事反應的就是命名空間這個概念的重要性,如果說,我們在故事中引入了命名空間這個概念,那麼廣播站的同學應該是這麼幫你播放愛的宣言的:
愛的宣言:世界上只有一個名字,使我這樣牽腸掛肚,像是一根看不見的線,一頭牢牢的系在我心尖上,一頭攥在你手中,這個名字叫做CSDN論壇的來自江南的妳......
這樣的話,其他論壇的小花就不會帶入了。我們這裡CSDN論壇,就是一個命名空間了。
所以,我們剛才的代碼,應該把命名空間加上,才能夠正常使用模塊中的函數:
  1. >>> hello.hi()
  2. Hi, everyone!
相信這種用法大家都知道,我只是作為一個概念給大家強調一下。
(二)導入模塊
我們知道import + 模塊名是我們經常使用的方法,我們這裡重新寫一個例子來計算攝氏度和華氏度之間的轉換,
  1. #模块名:TemperatureConversion.py
  2. def c2f(cel):
  3. fah = cel *1.8 + 32
  4. return fah
  5. def f2c(fah):
  6. cel = (fah - 32) / 1.8
  7. return cel
然後再寫一個文件來導入剛才的模塊:
  1. #文件名:calc.py
  2. import TemperatureConversion
  3. print("32摄氏度 = %.2f华氏度"%TemperatureConversion.c2f(32))
  4. print("99华氏度 = %.2f摄氏度"%TemperatureConversion.f2c(99))
運行結果:
  1. >>>
  2. 32摄氏度 = 89.60华氏度
  3. 99华氏度 = 37.22摄氏度
這就是我們的第一種方法:
  • 第一種:import 模塊名
  • 第二種:from 模塊名import 函數名(from 模塊名import * 這種方法不建議使用,因為這樣的話,命名空間的優勢就蕩然無存了,可能造成重名的困擾)
  • 第三種:import 模塊名as 新名字
這三種方法在我們之前講解EasyGui的時候都已經詳細講解過了,忘了的同學可以返回去看一下。

0 留言:

發佈留言