2020年9月17日星期四

[課後作業] 第048講:魔法方法:迭代器|課後測試題及答案

[課後作業] 第048講:魔法方法:迭代器|課後測試題及答案





《零基礎入門學習Python》視頻下載地址:傳送門
"X^L2#Z3mQ`PzYjur[$?1*(vxN89G
測試題(筆試,不能上機哦~):
yhpk0EN' P )2-dl:j4WO,?KT6tqF=
0.請用你的話解釋一下“迭代”的概念?"<6X0QO_]b
Pa,dt!E$k9|C#'LuYH>2Qf s
$QDAxliPq G-~sZpM]7){^nC
1.迭代器是一個容器嗎?版權屬於:bbs.fishc.com
m2lM$ _?v[K6e]Spwo*PN5
~W<UPl7cdRn|A>&ewvM V
2.迭代器可以回退(獲取上一個值)嗎?sD9Vc
Pezh3R:YS&i]@.g#^VbfrJq~'ptoa
g[?Nk `8m_M#f!PatbXy>lKwu'~F
3.如何快速判斷一個容器是否具有迭代功能?EeV ;Xn
+"!2$zx3(1LFc.A9RGqW5SNur:[8Jw
],3pi>LM2+roO#|.Rjfz ~k)I
4. for語句如何判斷迭代器裡邊已經取空了?kXt-:@U1Au
2bQ!)ruHq"[:
*0NZ@M9hUS8v%=rj&Il?+-1KcBA,:
5.在Python原生支持的數據結構中,你知道哪一個是只能用迭代器訪問的嗎?
'K[2#fr:I
Gd?~Elys!O'pmXvhtAN<IRD="r4c
zc,h[fr%DIK9kHXPQWa{ye@o7
動動手(一定要自己動手試試哦~):
>ht^.MI7(SV_i"f8FkN1`5&b
0.用while語句實現與以下for語句相同的功能:Vq+W-NLE

  1. for each in range(5):
  2.     print(each)
複製代碼

0u'K!:*7qgMplN,2Xvk$"#fr5zs&
1.寫一個迭代器,要求輸出至今為止的所有閏年。如:>6g|a#.s
  1. >>> leapYears = LeapYear()
  2. >>> for i in leapYears:
  3.         if i >=2000:
  4.                 print(i)
  5.         else:
  6.                 break

  7. 2012
  8. 2008
  9. 2004
  10. 2000
複製代碼

提示:閏年判定法((year%4 == 0 and year%100 != 0) or (year%400 == 0))8VJwH*c:d
mng7pJTz?|4B,8S`&'{lfaNC Z5_P
"_ >hV4,#ZdM1RDT<qnrSG[j
2.要求自己寫一個MyRev類,功能與reversed()相同(內置函數reversed(seq)是返回一個迭代器,是序列seq的逆序顯示)。例如:L)_ =bS
  1. >>> myRev = MyRev("FishC")
  2. >>> for i in myRev:
  3.     print(i, end='')

  4. ChsiF
複製代碼

3.請寫下這一節課你學習到的內容:格式不限,回憶並複述是加強記憶的好方式!2t|L@*mYGv5,?SP_(feNy-w{!D

請務必自己先動手,貪一時之快先看答案,您將失去一次鍛煉的機會。fM=:w
?3gl }~7Rq_do+=Li! )X
回复您的答案即可查看參考答案!
<nxZwP"W%Q
!$m&PxSik,FoLavrj sf[*|
7-ElIjwAx2u+yQ_goYM#S$p?@PXT
測試題答案:

本帖隱藏的內容

版權屬於:bbs.fishc.com
0.請用你的話解釋一下“迭代”的概念?H6$&@k
pOQ:+j5RHMl8uP9$xacg([m}o-is>B
答:迭代是重複反饋過程的活動,其目的通常是為了接近並到達所需的目標或結果。每一次對過程的重複被稱為一次“迭代”,而每一次迭代得到的結果會被用來作為下一次迭代的初始值。rgBYMs
Gt76M?WRvAChm(H%8,eQ[XO
o;tYn@^v[8.~ FGAe],akE4OCu{|3
1.迭代器是一個容器嗎?^,Yq4.SRLK
`@K0dn?H&oP',paS$FE6zB
答:不是。因為我們耳熟能詳的容器像列表,字典,元組都是可以存放數據的,而迭代器就是實現了__next__()方法的對象(用於遍歷容器中的數據)。0FY"}
zm~0D Xdn|'WLF#i]26kH
D$!hu*+yq`t ['iT@VfMWrl)8e_p4K
2.迭代器可以回退(獲取上一個值)嗎?o)Cie>5
"g!:08a|W.lU_%Now6{*=dm}31j,TD
答:迭代器性質決定沒有辦法回退,只能往前進行迭代。但這並不是什麼很大的缺點,因為我們幾乎不需要在迭代途中進行回退操作。$x?~)4J=k
F-^E8>CW)4+@wgc2$oj!v
T!r(<%&BgH+`)KD*y8d6>M1G3QRc
3.如何快速判斷一個容器是否具有迭代功能?gv-9.
W.>$!ym5}ETN8qQ)Gn l4*%]<kv'[9
答:判斷該容器是否擁有__iter__()和__next__()魔法方法。.QR m1S
r?,_@oGv~u43DYySk%z<][Wpd^fen
'*nDy#~`-j]LOY5ml|oI)q(W?,w.2v
4. for語句如何判斷迭代器裡邊已經取空了?PgT":VQGD>
90l3^Rz]nGgaV"_}|*PQ7TEj
答:迭代器通過__next__()方法每次返回一個元素,並指向下一個元素。如果當前位置已無元素,通過拋出StopIteration異常表示。@uOjhZ9_
1 ?M%Z_aC!W38qB^4txpnT+Lye9u*
t"pa}T~yu#9@YfD7L|4NIr
5.在Python原生支持的數據結構中,你知道哪一個是只能用迭代器訪問的嗎?7DsUFS);
pZ10'iJ7YB2.#"X+DsU<RG
答:set。對於原生支持隨機訪問的數據結構(如tuple、list),可以使用迭代器或者下標索引的形式訪問,但對於無法隨機訪問的數據結構set而言,迭代器是唯一的訪問元素的方式。"

來自:bbs.fishc.com
zJ5kba4e~-KcLx+#_q3(!UHnV
動動手答案:版權屬於:bbs.fishc.com

本帖隱藏的內容

版權屬於:bbs.fishc.com
0.用while語句實現與以下for語句相同的功能:w[oQ]
  1. for each in range(5):
  2.     print(each)
複製代碼

代碼清單:版權屬於:bbs.fishc.com
  1. alist = range(5)
  2. it = iter(alist)

  3. while True:
  4.     try:
  5.         print(next(it))
  6.     except StopIteration:
  7.         break
複製代碼

}ByKI1:(2dRYXCD.[zE-W]`S^8OJu3
1.寫一個迭代器,要求輸出至今為止的所有閏年。如:B"K jwL
  1. >>> leapYears = LeapYear()
  2. >>> for i in leapYears:
  3.         if i >=2000:
  4.                 print(i)
  5.         else:
  6.                 break

  7. 2012
  8. 2008
  9. 2004
  10. 2000
複製代碼

提示:閏年判定法((year%4 == 0 and year%100 != 0) or (year%400 == 0))'o!z8x
1;Mjb+{rop`nT}L!)6za|ml7w' kUd
代碼清單:版權屬於:bbs.fishc.com
  1. import datetime as dt

  2. class LeapYear:
  3.     def __init__(self):
  4.         self.now = dt.date.today().year

  5.     def isLeapYear(self, year):
  6.         if (year%4 == 0 and year%100 != 0) or (year%400 == 0):
  7.             return True
  8.         else:
  9.             return False
  10.         
  11.     def __iter__(self):
  12.         return self

  13.     def __next__(self):
  14.         while not self.isLeapYear(self.now):
  15.             self.now -= 1

  16.         temp = self.now
  17.         self.now -= 1
  18.         
  19.         return temp
複製代碼

<;%^ pbd+t!1ri7WoN>w]R|ya{*)
2.要求自己寫一個MyRev類,功能與reversed()相同(內置函數reversed(seq)是返回一個迭代器,是序列seq的逆序顯示)。例如:LTF5|b^
  1. >>> myRev = MyRev("FishC")
  2. >>> for i in myRev:
  3.     print(i, end='')

  4. ChsiF
複製代碼

代碼清單:Powered by bbs.fishc.com
  1. class MyRev:
  2.     def __init__(self, data):
  3.         self.data = data
  4.         self.index = len(data)
  5.         
  6.     def __iter__(self):
  7.         return self
  8.    
  9.     def __next__(self):
  10.         if self.index == 0:
  11.             raise StopIteration

  12.         self.index = self.index - 1
  13.         return self.data[self.index]
複製代碼

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

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

自始至終,有一個概念,我們一直都在使用,但是我們從來沒有認真地去剖析它,這個概念就是迭代
迭代的意思就類似於循環,每一次重複的過程被稱之為一次迭代的過程,而每一次迭代得到的結果將會被用來作為下一次迭代的初始值,那麼提供迭代方法的容器我們稱之為迭代器
通常我們接觸的迭代器有序列(序列就是列表、元組、字符串)和字典,它們都支持迭代操作,舉例說明:
我們通常使用for 語句進行迭代,
  1. >>> for i in "来自江南的你":
  2. print(i)
字符串就是一個容器,同時也是一個迭代器,for 語句的作用就是觸發這個迭代器的迭代功能,每次從容器裡面依次拿出一個數據,這就是所謂的迭代操作。同時,字典和文件也是支持迭代操作的,例如:
  1. >>> dict1 = {1 : 'one', 2 : 'two', 3 : 'three', 4 : 'four'}
  2. >>> for each in dict1:
  3. print("%s -> %s"%(each, dict1[each]))
  4. 1 -> one
  5. 2 -> two
  6. 3 -> three
  7. 4 -> four
關於迭代操作,Python提供了兩個BIF:iter() 和next()
對於一個容器對象,調用iter() 就得到它的迭代器,調用next() ,迭代器就會返回下一個值,那麼怎麼結束呢,如果沒有值可以返回了,Python 就會拋出一個StopIteration 的異常。舉例:
  1. >>> string = '来自江南的你'
  2. >>> it = iter(string)
  3. >>> next(it)
  4. '来'
  5. >>> next(it)
  6. '自'
  7. >>> next(it)
  8. '江'
  9. >>> next(it)
  10. '南'
  11. >>> next(it)
  12. '的'
  13. >>> next(it)
  14. '你'
  15. >>> next(it)
  16. Traceback (most recent call last):
  17. File "<pyshell#47>", line 1, in <module>
  18. next(it)
  19. StopIteration
我們知道for 語句是自動調用迭代器的,那麼通過這兩個BIF 我們大概就能分析出for 語句的工作原理:
  1. >>> while True:
  2. try:
  3. each = next(it)
  4. except StopIteration:
  5. break
  6. print(each)
大家看到了,我們用while 語句同樣可以還原for 語句,
  1. >>> for each in string:
  2. print(each)
那麼,我們現在講的是魔法方法,關於迭代器,它的魔法方法一共是兩個:__iter__() 和 __next__()
  • iter()
__iter__()
  • next()
__next__()
沒錯,它們對應的就是剛才的兩個BIF的實現,一個容器如果是迭代器,那麼就應該實現__iter__() 這個魔法方法,這個方法其實是返回迭代器本身,就是return(self),接下來重點要實現的是__next__() 這個魔法方法,因為它跌定了迭代器的規則,舉個簡單的例子:
  1. #斐波那契数列
  2. >>> class Fibs:
  3. def __init__(self):
  4. self.a = 0
  5. self.b = 1
  6. def __iter__(self):
  7. return self
  8. def __next__(self):
  9. self.a, self.b = self.b, self.a + self.b
  10. return self.a
  11. >>> fibs = Fibs()
  12. >>> for each in fibs:
  13. print(each)
  14. 1
  15. 1
  16. 2
  17. 3
  18. 5
  19. ...
這個會沒完沒了,不能停下來,但是基本功能實現了,下面改進,加一個限制條件(20以內的數列):
  1. >>> for each in fibs:
  2. if each < 20:
  3. print(each)
  4. else:
  5. break
  6. 1
  7. 1
  8. 2
  9. 3
  10. 5
  11. 8
  12. 13
我們發現了,我們剛剛實現的這個迭代器的惟一的亮點就是沒有終點,我們可以加入一個參數來控制迭代的範圍:
  1. >>> class Fibs:
  2. def __init__(self, n = 10):
  3. self.a = 0
  4. self.b = 1
  5. self.n = n
  6. def __iter__(self):
  7. return self
  8. def __next__(self):
  9. self.a, self.b = self.b, self.a + self.b
  10. if self.a > self.n:
  11. raise StopIteration
  12. return self.a
這樣就不會沒完沒了了:
  1. >>> fibs = Fibs()
  2. >>> for each in fibs:
  3. print(each)
  4. 1
  5. 1
  6. 2
  7. 3
  8. 5
  9. 8
而且,你可以控制它的數量,這裡改為100:
  1. >>> fibs = Fibs(100)
  2. >>> for each in fibs:
  3. print(each, end = ' ')
  4. 1 1 2 3 5 8 13 21 34 55 89

0 留言:

發佈留言