Karinoya 學習室 證照 Cloud / AI / Python 合格實驗室 控制結構與資料結構
日本語 English Français Bahasa Indonesia 한국어 Română ไทย Tiếng Việt 简体中文 繁體中文
證照 · Cloud / AI / Python 合格實驗室
控制結構與資料結構 可以用繁體中文閱讀題目與解說。講義(解說文章)僅有日文版。
查看日文版(含講義) →
第1題 | for/else
執行下列在for陳述式加上else子句的程式碼時,輸出的內容是哪一項?
for n in range(4): if n == 9: break else: print("done") print(n) 只輸出 3,不會出現 done 只輸出 done,不會出現 3 依序輸出 3 與 done 依序輸出 done 與 3 正確答案 D. 依序輸出 done 與 3 加在for後面的else子句,會在迴圈沒有被break、正常結束時執行。由於 range(4) 之中沒有9,break一次都不會發生,跑完整個迴圈後else的print才會動作,輸出 done。之後的 print(n) 會輸出跳出迴圈時n所殘留的最後一個值3。若把輸出順序弄反,就會變成3先出現的形式;若誤以為else在迴圈結束時一定會被跳過,就會變成不出現done的形式;若忽略n在跳出迴圈後仍會保留下來,就會變成不出現3的形式。
第2題 | break與else
確認以break跳出迴圈時else子句會如何處理。下列程式碼的輸出是哪一項?
for c in "abc": if c == "b": break print(c) else: print("no break") 全部輸出 a b c 與 no break 依序輸出 a 與 no break 依序輸出 a 與 b 這2個 輸出 a,不輸出 no break 正確答案 D. 輸出 a,不輸出 no break 第1輪c是a,因此 print(c) 執行,輸出a。第2輪c變成b,以break中止迴圈。for的else子句規定只有在沒被break、正常結束時才會執行,因此這裡會被跳過,不會出現no break。若誤以為else在迴圈結束時一定會執行,就會連no break都跑出來;若誤讀成print(c)在break之前就已執行,就會連b都跑出來。若忽略break本身,則會變成a b c全部都輸出。
第3題 | 空的也有else
詢問當迭代對象為空時,for的else子句會如何處理。下列程式碼的執行結果是哪一項?
items = [] for it in items: print(it) else: print("finished") else子句被忽略,發生 TypeError 由於迭代0次,發生 StopIteration 什麼都不輸出就跳出迴圈結束 只輸出1次 finished 正確答案 D. 只輸出1次 finished for的else子句被執行的條件是「迴圈沒有被break而結束」,而不是「至少迭代過1次」。由於items是空的,主體一次都不會執行,但由於也沒有break,else仍會照常執行,輸出finished。若以為空的話else也會被跳過,就會變成什麼都不輸出的形式。把空列表傳給for本身是正確的寫法,不會產生例外,也不會拋出TypeError或StopIteration。
第4題 | while/else
在while陳述式加上else子句,並在途中break。下列程式碼的輸出是哪一項?
n = 5 while n > 0: n -= 1 if n == 2: break else: print("loop ended") print(n) 輸出 0,不輸出 loop ended 輸出 2,不輸出 loop ended 依序輸出 loop ended 與 2 依序輸出 loop ended 與 0 正確答案 B. 輸出 2,不輸出 loop ended n從5開始每次減1,經過4、3後在變成2的時間點break。while的else子句與for相同,只有在沒被break、正常結束時才會執行,因此這裡會被跳過,不會出現loop ended。剩下的只有print(n)的2。若以為else一定會執行,就會連loop ended都跑出來;若忽略break、誤以為會一直跑到條件變假為止,就會誤讀成n變成0的形式。
第5題 | continue
執行下列在同一個迴圈中混用continue與break的程式碼時,最後輸出的列表是哪一項?
out = [] for i in range(6): if i == 3: continue if i == 5: break out.append(i) print(out) [0, 1, 2, 4, 5] [0, 1, 2, 3] [0, 1, 2, 4] [0, 1, 2, 3, 4] 正確答案 C. [0, 1, 2, 4] 當i是0、1、2時,會通過2個if,因此被append。當i是3時continue生效,跳過該輪剩下的部分,也就是append被跳過。當i是4時再次被append,當i是5時以break中止迴圈,因此append不會執行。所以結果是 [0, 1, 2, 4]。若以為break那一輪也會被加入,就會變成排到5的形式;若把continue當成pass來處理,就會變成3也留下來的形式。
第6題 | range的逆序
詢問對range傳入負的步進值時的排列。下列程式碼的輸出是哪一項?
print(list(range(10, 0, -3))) [9, 6, 3, 0] [7, 4, 1, -2] [10, 7, 4, 1, 0] [10, 7, 4, 1] 正確答案 D. [10, 7, 4, 1] range(start, stop, step) 會從start開始,每次前進step,在到達stop之前停止。這裡從10開始每次減3,依序是10、7、4、1,下一個 -2 已經小於等於0,因此不會被採用。由於不包含stop的0,不會出現末尾排列著0的形式。若誤以為不包含start,就會變成從7開始的形式;若誤以為從start的前一個開始數,就會變成從9開始的形式。不包含stop這一點,與正的步進值時相同。
第7題 | range的型別
關於呼叫內建函式range所得到的物件,下列說明何者恰當?
是generator型別的物件,迭代一次後就會變空 是range型別的物件,傳給list()就會變成列表 是tuple型別的物件,無法替換元素 是list型別的物件,會直接以帶方括號的形式顯示 正確答案 B. 是range型別的物件,傳給list()就會變成列表 range回傳的是range型別的物件,會依需要逐一計算並回傳所需的整數。它不像列表那樣事先持有全部元素,因此即使範圍很大也不會佔用太多記憶體。若想排列出內容確認,可以傳給list()。type(range(3)) 是range,既不是list也不是tuple,直接顯示時也不會呈現元素排列,而是輸出 range(0, 3)。此外它並非一次性用完,可以反覆迭代多次,因此也不是generator。順帶一提,能以索引讀取、無法替換元素這點與tuple相同,因此光憑這個性質無法與tuple區分。
第8題 | 短路求值
確認邏輯運算子or與and會回傳什麼。下列程式碼的輸出是哪一項?
print([] or 0 or "z") print(1 and 0 and 2) 依序輸出 True 與 False 依序輸出 False 與 0 依序輸出 z 與 0 依序輸出 z 與 2 正確答案 C. 依序輸出 z 與 0 or會由左至右求值,回傳第一個為真的值本身。空列表與0都是假,因此會回傳最後的 "z"。and則相反,會回傳第一個為假的值,因此1為真,接著0確定為假就回傳0,最右邊的2不會被求值。回傳的不是真假值,而是停止求值那一刻的值本身,因此不會出現True或False。and回傳最右邊的2,只有在途中全部為真的情況才會發生。
第9題 | 鏈式比較
執行下列結合鏈式比較與三元運算子的程式碼時,輸出的內容是哪一項?
x = 3 print(1 < x < 5) print("yes" if x % 2 else "no") 依序輸出 True 與 yes 依序輸出 True 與 no 依序輸出 False 與 no 依序輸出 False 與 yes 正確答案 A. 依序輸出 True 與 yes 1 < x < 5 與 (1 < x) and (x < 5) 意義相同,若x是3,兩者都成立,因此是True。三元運算子的排列方式是「真時的值 if 條件 else 假時的值」,這裡的條件是 x % 2,也就是1。在Python中,非0的整數會被當作真,因此會選擇yes。若把鏈式比較誤讀成從後方結合、像 1 < (x < 5) 那樣,x < 5 就會是True也就是1,於是變成 1 < 1 而得出False的誤答。此外,若把1當作假,就會變成選擇no的形式。
第10題 | pass的作用
關於Python的pass陳述式,下列說明何者恰當?
表示中止迴圈本身並跳出 在語法上需要有區塊的位置,表示不做任何事 表示跳過迴圈剩下的部分,前進到下一次迭代 表示結束函式的執行,並向呼叫端回傳值 正確答案 B. 在語法上需要有區塊的位置,表示不做任何事 Python以縮排表示區塊,因此無法寫出空的區塊。當打算之後再撰寫類別或函式的內容,或是在符合條件時刻意什麼都不做時,pass就用來填補該處位置。它本身不具備改變處理流程的作用。前進到下一次迭代的是continue,中止迴圈的是break,向呼叫端回傳值的是return,這些的作用都與pass不同。
第11題 | enumerate
執行下列對enumerate傳入第2引數的程式碼時,畫面上出現的是哪一項?
for i, name in enumerate(["gu", "choki", "pa"], 1): print(i, name) 輸出3行 1 gu / 2 choki / 3 pa 輸出3行 0 gu / 1 choki / 2 pa 輸出3行 gu 1 / choki 2 / pa 3 只輸出2行 1 gu / 2 choki 正確答案 A. 輸出3行 1 gu / 2 choki / 3 pa enumerate會依序回傳 (編號, 元素) 這樣的元組,並可用第2引數start指定開始計數的值。這裡傳入了1,因此編號是1、2、3。若與省略start時預設的0開始搞混,就會變成從0開始的形式。回傳的元組是編號在前、元素在後,因此 print(i, name) 的排列順序也依此順序,不會是名稱先出現。3個元素都會被取出,因此也不會只輸出2行就中止。
第12題 | zip的長度
把長度不同的2個列表傳給zip。下列程式碼的執行結果是哪一項?
print(list(zip([1, 2, 3], [10, 20]))) [(1, 10), (2, 20)] [(1, 10), (2, 20), (3,)] [(1, 10), (2, 20), (3, 0)] [(10, 1), (20, 2)] 正確答案 A. [(1, 10), (2, 20)] zip會從傳入的各個可迭代物件中逐一取出並組成一組,一旦最短的那個用完就結束。這裡由於第2個列表只有2個元素,因此只會組成2組,多出來的3會被靜靜地捨棄。不會發生錯誤,也不會用0來補齊剩餘部分,或做出只有一半的單獨元組。組的內容依傳入的順序排列,因此不會像10與1那樣被調換。
第13題 | 用zip拆解
把組成組的資料,加上星號後重新傳給zip。下列程式碼的輸出是哪一項?
pairs = [(1, 'a'), (2, 'b'), (3, 'c')] nums, chars = zip(*pairs) print(nums) print(chars) 先輸出 [1, 2, 3],接著輸出 ['a', 'b', 'c'] 先輸出 (1, 2, 3),接著輸出 ('a', 'b', 'c') 先輸出 ((1, 'a'),),接著輸出 ((2, 'b'),) 先輸出 (1, 'a'),接著輸出 (2, 'b') 正確答案 B. 先輸出 (1, 2, 3),接著輸出 ('a', 'b', 'c') 加上星號後,列表中的各個組會分別作為個別的引數傳給zip。也就是等同於呼叫 zip((1, 'a'), (2, 'b'), (3, 'c')),把各組的第1個彼此、第2個彼此彙整起來,分成 (1, 2, 3) 與 ('a', 'b', 'c') 這2個。這是把組成組的資料還原回原本2份資料的固定寫法,把zip再套用一次就能還原。由於回傳的是元組而非列表,不會呈現方括號的形式。若忘記加星號寫成 zip(pairs),組本身就會作為單一引數傳入,變成像 ((1, 'a'),) 這樣只有1個元素的元組排列的形式。
第14題 | dict與zip
從鍵的排列與值的排列組建字典。下列程式碼的執行結果是哪一項?
keys = ["a", "b", "c"] vals = [10, 20, 30] print(dict(zip(keys, vals))) [('a', 10), ('b', 20), ('c', 30)] {10: 'a', 20: 'b', 30: 'c'} {'a', 'b', 'c', 10, 20, 30} {'a': 10, 'b': 20, 'c': 30} 正確答案 D. {'a': 10, 'b': 20, 'c': 30} zip(keys, vals) 會依序回傳 (鍵, 值) 這樣的元組,dict() 會接收這一連串的組來建立字典。組的第1個是鍵、第2個是值,因此不會變成數值當鍵的形式。由於是傳給dict()處理,也不會維持成元組列表的形式。即使以花括號顯示,用冒號組成一對的是字典,只有值排列的則是集合。
第15題 | 列表生成式
執行下列使用列表生成式的程式碼時,輸出的列表是哪一項?
print([n * n for n in range(1, 5)]) [0, 1, 4, 9] [2, 4, 6, 8] [1, 4, 9, 16] [1, 4, 9, 16, 25] 正確答案 C. [1, 4, 9, 16] range(1, 5) 回傳的是1、2、3、4,不包含指定為stop的5。各自平方後就是1、4、9、16。若誤以為range從0開始,就會變成從0排列的形式;若誤解成包含stop,就會變成排到25的形式;若把 n * n 誤讀成 n * 2,就會變成每次加2的形式。生成式的讀法是:對每個元素求出最左邊的算式的值,再排成新的列表,最好牢記這個讀法。
第16題 | 字典生成式
執行在花括號中加上冒號的生成式。下列程式碼的輸出是哪一項?
words = ["sun", "moon"] print({w: len(w) for w in words}) {'sun': 3, 'moon': 4} [('sun', 3), ('moon', 4)] {3: 'sun', 4: 'moon'} {'sun', 'moon', 3, 4} 正確答案 A. {'sun': 3, 'moon': 4} 花括號中帶有冒號的生成式是字典生成式,冒號左邊是鍵、右邊是值。這裡會做出以單字為鍵、其字元數為值的字典。若把鍵與值反過來讀,就會變成字元數當鍵的形式。若用方括號包起來會變成元組列表,但這裡是花括號,因此不會是那種形式。若沒有冒號就會是集合生成式,只會顯示值排列的樣子,但既然有冒號,做出來的就會是字典。
第17題 | 圓括號的型別
把類似生成式的算式用圓括號括起來。執行下列程式碼時,顯示的型別是哪一項?
g = (n for n in range(3)) print(type(g)) <class 'range'> <class 'list'> <class 'generator'> <class 'tuple'> 正確答案 C. <class 'generator'> Python並沒有所謂的元組生成式寫法,用圓括號包起來的這種形式,會變成生成器表達式。型別是generator,不會事先把值全部生成,而是在被要求時才逐一計算,因此省記憶體,但由於是迭代器,用過一次就會用盡。若想要元組,要用tuple()包起來。用方括號寫就會變成列表生成式而得到list,若直接把 range(3) 賦值則會得到range。tuple無法透過這種寫法得到。
第18題 | 集合生成式
計算以集合生成式建立之容器的元素數量。下列程式碼的輸出是哪一項?
print(len({n % 4 for n in range(10)})) 輸出 3 輸出 0 輸出 10 輸出 4 正確答案 D. 輸出 4 range(10) 各個值除以4的餘數依序是0、1、2、3、0、1、2、3、0、1。花括號中沒有冒號的生成式是集合生成式,因此重複的值會被彙整成1個,最後剩下0、1、2、3這4種。若忽略重複會被消除、直接數值的個數,就會得到10。若忽略餘數中包含0、數成1、2、3這3種,就會得到3。0是誤以為生成式什麼都沒做出來時的值,但只要跑過range(10),內容就不會是空的。由於集合的顯示順序不固定,用元素數量來確認比較可靠。
第19題 | 雙重生成式
詢問並列2個for的生成式的排列順序。下列程式碼的執行結果是哪一項?
print([(x, y) for x in [1, 2] for y in "ab"]) [(1, 'a'), (2, 'b'), (1, 'b'), (2, 'a')] [('a', 1), ('b', 1), ('a', 2), ('b', 2)] [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')] [(1, 'a'), (2, 'a'), (1, 'b'), (2, 'b')] 正確答案 C. [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')] 在生成式中並列2個for時,寫在左邊的for會是外層迴圈。這與把一般for陳述式寫成巢狀結構時的順序完全相同,會先把x固定為1,讓y依a、b跑一輪,接著把x變成2,重複同樣的事。若把右邊的for讀成外層,就會變成x先跑的順序。組的內容依算式中所寫的 (x, y) 排列,因此不會是文字排在前面的形式。
第20題 | start引數
關於內建函式enumerate的第2引數start,下列說明何者恰當?
指定開始計數的編號。省略時從0開始計數 指定要從哪個元素開始取出。省略時從開頭取起 指定每次要跳過幾個。省略時每次前進1個 指定要數到第幾個為止。省略時數到最後 正確答案 A. 指定開始計數的編號。省略時從0開始計數 enumerate的第2引數start,只決定所附加編號要從幾開始。預設是0,若傳入1,就會變成人類慣用的流水編號。只有編號的方式改變,取出的元素範圍或個數並不會改變,這一點是重點。它並不具備限制個數或跳過的作用,也不是用來移動取出的起始位置。這些都是切片等其他工具的說明。
第21題 | sort的回傳值
用變數接收列表sort方法的回傳值。下列程式碼的輸出是哪一項?
nums = [5, 3, 9] result = nums.sort() print(result) print(nums) 依序輸出 [3, 5, 9] 與 [3, 5, 9] 依序輸出 None 與 [5, 3, 9] 依序輸出 [3, 5, 9] 與 [5, 3, 9] 依序輸出 None 與 [3, 5, 9] 正確答案 D. 依序輸出 None 與 [3, 5, 9] sort是就地排序列表的方法,回傳值是None。因此result會存入None,排序後的結果會留在nums這一側。若誤以為會回傳排序後的新列表,就會變成result那邊存有列表的形式。若忽略sort會改變原列表,就會變成nums維持原本排列的形式。若想在保留原本內容的同時取得排序後的列表,要使用內建函式sorted。
第22題 | sorted的差異
關於列表的sort方法與內建函式sorted的差異,下列何者恰當?
sort回傳新列表,sorted就地排序並回傳None sort就地排序並回傳None,sorted回傳新列表 兩者都會回傳新列表,原本的列表都不會改變 兩者都會就地排序,並回傳排序後的列表 正確答案 B. sort就地排序並回傳None,sorted回傳新列表 sort是列表的方法,會排序該列表自身,回傳值是None。sorted是內建函式,完全不改變原本的排列,回傳排序後的新列表。要依是否想保留原本內容來選用。若把兩者的角色互換記憶,就會變成sort回傳新列表的說明。若把是否具破壞性的性質統一套用在一方,就會變成兩者都就地排序、或兩者都不改變原本內容的說明。順帶一提,sorted也能接收列表以外的可迭代物件,結果一律會是列表。
第23題 | append的差異
比較把另一個列表加入列表的2種方法。下列程式碼的輸出是哪一項?
a = [1, 2] a.append([3, 4]) b = [1, 2] b.extend([3, 4]) print(a, b) [1, 2, [3, 4]] [1, 2, [3, 4]] [1, 2, 3, 4] [1, 2, [3, 4]] [1, 2, 3, 4] [1, 2, 3, 4] [1, 2, [3, 4]] [1, 2, 3, 4] 正確答案 D. [1, 2, [3, 4]] [1, 2, 3, 4] append會把引數整個當作1個元素加到末尾,因此若傳入列表就會形成巢狀結構,長度只增加1。extend則會把引數逐一迭代取出後加入,因此內容會被拆開,長度增加2。若把2者的角色互換,a與b的結果就會顛倒。若以為兩者作用相同,就會變成兩者都巢狀化、或兩者都攤平的形式。兩個方法的回傳值都是None,因此不能用變數接收其結果,這一點也要一併記住。
第24題 | 淺拷貝
用切片複製巢狀列表,並改寫內層。下列程式碼的執行結果是哪一項?
orig = [[1, 2], [3, 4]] copy1 = orig[:] copy1[0].append(9) print(orig) [[1, 2, 9], [3, 4, 9]] [[1, 2, 9], [3, 4]] [[1, 2], [3, 4]] [[1, 2], [3, 4], 9] 正確答案 B. [[1, 2, 9], [3, 4]] 透過切片複製是淺拷貝,外層列表會重新建立,但內部所含的元素仍與原本共用同一個。copy1[0]與orig[0]指向同一個列表,因此對其append,原本那一側也會看到變化。若誤以為能完全切割開來,就會變成原本不受影響的形式。由於只改寫了最前面的內層列表,不會延伸到後面的元素,也沒有加到外層,因此9不會排列在外層。若想連內層都切割開來,要使用copy.deepcopy。
第25題 | 深拷貝
在一段程式碼中比較深拷貝與淺拷貝。執行後base會變成什麼?
import copy base = [[1, 2], [3, 4]] d = copy.deepcopy(base) s = base[:] d[0].append(8) s[1].append(7) print(base) [[1, 2], [3, 4]] [[1, 2, 8], [3, 4, 7]] [[1, 2, 8], [3, 4]] [[1, 2], [3, 4, 7]] 正確答案 D. [[1, 2], [3, 4, 7]] copy.deepcopy會連巢狀的內容也一併複製,因此d[0]會是與base[0]不同的列表,對它append不會影響到base。另一方面,s是淺拷貝,因此s[1]與base[1]是同一個列表,對它append也會反映到base上。因此只有後面的元素會延伸。若以為兩者都會影響到,就會變成內層2個都延伸的形式;若以為兩者都不會影響,就會變成維持原狀的形式。若把深拷貝與淺拷貝搞混,就會變成只有前面的元素延伸的形式。
第26題 | 乘法的陷阱
試圖用列表乘法做出二維表格。下列程式碼的執行結果是哪一項?
grid = [[0] * 3] * 2 grid[0][1] = 5 print(grid) [[0, 0, 0], [0, 5, 0]] [[5, 0, 0], [5, 0, 0]] [[0, 5, 0], [0, 0, 0]] [[0, 5, 0], [0, 5, 0]] 正確答案 D. [[0, 5, 0], [0, 5, 0]] 外層的乘法並不會建立新的每一列,只是把同一個列表的參照排列了2次。grid[0]與grid[1]是同一個實體,因此改寫其中一方索引1的位置,另一方看起來相同位置也會改變。若以為各列彼此獨立,就會變成只有其中一列改變的形式。由於改寫的是索引1的位置,也不會變成開頭是5的形式。若想讓各列彼此獨立,要寫成 [[0] * 3 for _ in range(2)]。
第27題 | 單元素元組
比較只用圓括號包起來的值,與在末尾加上逗號的值的型別。下列程式碼的輸出是哪一項?
x = (7) y = (7,) print(type(x).__name__, type(y).__name__) 依序輸出 int 與 int 依序輸出 tuple 與 tuple 依序輸出 tuple 與 int 依序輸出 int 與 tuple 正確答案 D. 依序輸出 int 與 tuple 決定是否為元組的不是圓括號而是逗號。(7) 只是用來表示計算優先順序的括號括起來的整數,因此型別是int;要在末尾加上逗號寫成 (7,),才會成為只有1個元素的元組。若誤以為只要用括號括起來就會變成元組,就會變成兩者都是tuple的形式;若把兩者搞混,就會變成順序顛倒、或兩者都是int的形式。順帶一提,只有空元組是例外,要寫成不帶逗號的 ()。
第28題 | 元組的內容
試圖對放在元組中的列表加入元素。下列程式碼的執行結果是哪一項?
t = (1, [2, 3], 4) t[1].append(5) print(t) 拋出 TypeError (1, [2, 3], 4, 5) (1, [2, 3, 5], 4) (1, [2, 3], 4) 正確答案 C. (1, [2, 3, 5], 4) 元組凍結的是「指向哪個元素」這樣的對應關係,並不會凍結所指對象的內容。t[1]是一個列表,該列表本身是可變的,因此可以append。像 t[1] = [] 這樣直接對元組的元素賦值會產生TypeError,但這裡並沒有替換元素。由於加入的是列表內部,元組的長度不會增加,也不會完全不變。
第29題 | 切片賦值
對列表的切片賦予長度不同的列表。下列程式碼的輸出是哪一項?
x = [1, 2, 3, 4, 5] x[1:3] = [9] print(x) [1, 9, 4, 5] [1, 9, 3, 4, 5] [1, 9, 9, 4, 5] [1, 2, 9, 4, 5] 正確答案 A. [1, 9, 4, 5] 對切片賦值是把指定範圍整個替換成右邊內容的操作。x[1:3] 指的是2與3這2個元素,會被替換成9這1個元素,因此整體長度從5減為4。若以為只會替換1個元素,就會變成長度仍是5的形式;若以為右邊會依範圍寬度延伸,就會變成排出2個9的形式。若把範圍起點誤讀成往後移1格,就會變成2留下來的形式。左邊的寬度與右邊的長度可以不同,正是切片賦值的特徵。
第30題 | 插入與刪除
連續進行對寬度為0之切片的賦值與del。下列程式碼的執行結果是哪一項?
y = [1, 2, 3] y[1:1] = [7, 8] del y[0] print(y) [7, 8, 3] [1, 7, 8, 3] [7, 8, 2, 3] [2, 3, 7, 8] 正確答案 C. [7, 8, 2, 3] y[1:1] 是寬度為0的範圍,因此對它賦值會變成不伴隨刪除的插入,列表變成 [1, 7, 8, 2, 3]。接下來的 del y[0] 會移除開頭的1,因此留下 [7, 8, 2, 3]。若誤讀成插入時原有的元素也會被消掉1個,就會變成7 8 3的形式;若以為del會刪除別的位置,就會變成開頭的1保留下來的形式。若誤讀成加到末尾,就會變成2與3排在前面的形式。del是陳述式,沒有回傳值,且不取出值就直接刪除,這一點也要一併掌握。
第31題 | get的預設值
用get查找字典中不存在的鍵。執行下列程式碼時輸出的內容是哪一項?
d = {"a": 1, "b": 2} print(d.get("z"), d.get("z", 0)) 依序輸出 None 與 0 第1個就拋出 KeyError 依序輸出 None 與 None 依序輸出 0 與 0 正確答案 A. 依序輸出 None 與 0 get在找不到鍵時不會拋出例外,若省略第2引數會回傳None,若有傳入則回傳該值。因此第1個是None,第2個是0。若以為即使沒有第2引數也會回傳0,就會變成兩者都是0;若以為第2引數會被忽略,就會變成兩者都是None。用方括號寫成 d["z"] 會產生KeyError,而為了避免這種情況所使用的工具就是get。
第32題 | setdefault
對已存在的鍵與不存在的鍵,分別呼叫setdefault。下列程式碼的輸出是哪一項?
d = {"a": 1} print(d.setdefault("a", 99)) print(d.setdefault("b", 99)) print(d) 99 與 99 後輸出 {'a': 99, 'b': 99} 1 與 99 後輸出 {'a': 1, 'b': 99} 1 與 None 後輸出 {'a': 1, 'b': None} 1 與 99 後輸出 {'a': 1} 正確答案 B. 1 與 99 後輸出 {'a': 1, 'b': 99} setdefault若鍵已存在,只會回傳既有的值,不會改變字典。若鍵不存在,會把第2引數作為值插入,並回傳該值。因此第1次會回傳既有的1,字典維持不變;第2次會插入99,並回傳99。若以為既有的值也會被覆寫,就會變成兩者都是99的形式;若以為不會發生插入,就會變成字典沒有增加的形式。若省略第2引數,插入的值會是None,因此變成None的形式,是沒有寫第2引數時的結果。
第33題 | in檢查的對象
確認字典的in運算子檢查的是什麼。下列程式碼的輸出是哪一項?
d = {"x": 1, "y": 2} print("x" in d, 1 in d, 1 in d.values()) 依序輸出 True False True 依序輸出 True True True 依序輸出 True False False 依序輸出 False True True 正確答案 A. 依序輸出 True False True 對字典使用in只會檢查鍵。由於"x"是鍵,所以是True;1雖然作為值存在,但不是鍵,所以是False。若想檢查值,可以把d.values()作為對象,這樣就會是True。若以為in也會檢查值,就會全部變成True;若以為即使對values()檢查也不看值,就會變成最後一個是False。若把鍵與值的角色互換來讀,就會變成第一個是False。先確認鍵是否存在,再用方括號取值,是常見的固定用法。
第34題 | 鍵的重複
在字典的字面值中重複寫了2次相同的鍵。下列程式碼的執行結果是哪一項?
d = {"a": 1, "b": 2, "a": 3} print(d) {'a': 3, 'b': 2} {'a': 1, 'b': 2} {'b': 2, 'a': 3} {'a': 3, 'b': 3} 正確答案 A. {'a': 3, 'b': 2} 字典的字面值會由左至右依序建立項目,因此若同一個鍵出現2次,後面的值會覆蓋前面的值。不會產生錯誤或警告。若以為先寫的會被保留,就會變成a的值仍是1的形式。此外字典會保持插入順序,覆寫並不會改變位置,因此仍會維持a排在前面的順序。因此不會發生鍵的順序互換,也不會連b的值都被牽連改變。
第35題 | 字典的建立方式
比較從關鍵字引數建立的字典,與從組的排列建立的字典。下列程式碼的輸出是哪一項?
d1 = dict(x=1, y=2) d2 = dict([("x", 1), ("y", 2)]) print(d1 == d2) print(d1) 先輸出 False,後輸出 {'x': 1, 'y': 2} 先輸出 True,後輸出 {1: 'x', 2: 'y'} 先輸出 True,後輸出 {'x': 1, 'y': 2} 先輸出 True,後輸出 [('x', 1), ('y', 2)] 正確答案 C. 先輸出 True,後輸出 {'x': 1, 'y': 2} dict既能從關鍵字引數建立字典,也能從 (鍵, 值) 的組排列建立字典。不論哪種寫法,做出來的字典內容相同,因此比較結果是True。若以為建立方式不同就會是不同的東西,就會變成比較結果為False。由於關鍵字引數的名稱會直接變成鍵的字串,因此鍵與值不會互換。由於已經傳給dict處理,也不會維持組排列的原樣。
第36題 | 空的花括號
比較空的花括號與set()的型別。執行下列程式碼時,顯示的2個型別名稱是哪一項?
a = {} b = set() print(type(a).__name__, type(b).__name__) 依序輸出 dict 與 dict 依序輸出 set 與 set 依序輸出 dict 與 set 依序輸出 set 與 dict 正確答案 C. 依序輸出 dict 與 set 有內容的 {1, 2} 會是集合,但若內容是空的,就無法判定是字典還是集合。Python在這種情況下會當作字典處理,因此 {} 是空字典。若想要空集合,只能寫成 set()。若以為花括號一律代表集合,就會變成兩者都是set的形式;若把兩者搞混,順序就會顛倒。若以為連set()也會變成字典,就會變成兩者都是dict的形式。由於集合與字典都使用花括號,這個區別很容易搞混。
第37題 | 集合的運算
對2個集合進行交集與對稱差的運算。下列程式碼的輸出是哪一項?
s1 = {1, 2, 3, 4} s2 = {3, 4, 5} print(sorted(s1 & s2), sorted(s1 ^ s2)) 依序輸出 [3, 4] 與 [1, 2, 3, 4, 5] 依序輸出 [1, 2, 5] 與 [3, 4] 依序輸出 [3, 4] 與 [1, 2] 依序輸出 [3, 4] 與 [1, 2, 5] 正確答案 D. 依序輸出 [3, 4] 與 [1, 2, 5] &符號是交集,會留下兩者共有的3與4。^符號是對稱差,會蒐集只存在於其中一方的元素,因此只在s1的1與2、只在s2的5會留下,共通的3與4會被去除。若把對稱差與差集搞混,就會變成缺少5的形式;若把2個運算對調,輸出的順序就會顛倒。若把對稱差與聯集搞混,就會變成連3與4都包含在內的形式。由於集合的顯示順序不固定,這裡是用sorted排序後確認的。
第38題 | 去除重複
把有重複的列表放入集合。執行下列程式碼時的輸出是哪一項?
data = [3, 1, 3, 2, 1, 1] print(len(set(data)), sorted(set(data))) 依序輸出 6 與 [3, 1, 3, 2, 1, 1] 依序輸出 6 與 [1, 2, 3] 依序輸出 3 與 [3, 1, 2] 依序輸出 3 與 [1, 2, 3] 正確答案 D. 依序輸出 3 與 [1, 2, 3] 把列表傳給set會去除重複,剩下的值有1、2、3這3種,因此長度是3。把集合傳給sorted會回傳依大小升序排列的新列表。若以為重複會保留,就會變成個數為6的形式。sorted並不是依原本出現的順序,而是依大小排序,因此不會依最初出現的順序排列。集合本身的顯示順序沒有意義,若想排列,就要通過sorted處理。
第39題 | 元素的條件
試圖依序把元組與列表加入集合。執行下列程式碼會發生什麼事?
s = set() s.add((1, 2)) s.add([3, 4]) print(len(s)) 輸出 1,列表被轉換成了元組 發生 TypeError,列表無法放入集合 發生 ValueError,元素型別不能混用 輸出 2,兩個元素都放進了集合 正確答案 B. 發生 TypeError,列表無法放入集合 集合的元素與字典的鍵必須是可雜湊的。元組由於內容無法改變,是可雜湊的,因此可以加入;但列表由於之後內容可能改變,並非可雜湊,因此會產生訊息為unhashable type的TypeError。若以為兩者都能放入,就會變成輸出2的形式;若以為會隱含轉換成元組,就會變成輸出1的形式。型別混用本身並不是問題,因此以「型別混用」為理由主張會發生ValueError也是錯誤的。
第40題 | 3種取出方式
關於字典的方法keys、values、items各自回傳什麼,下列組合何者恰當?
keys回傳值的組,values回傳鍵的組,items回傳項目數 keys回傳鍵與值的組,values回傳鍵,items回傳值 keys回傳值,values回傳鍵,items回傳值彼此的組 keys回傳鍵,values回傳值,items回傳鍵與值的組 正確答案 D. keys回傳鍵,values回傳值,items回傳鍵與值的組 keys只回傳鍵,values只回傳值,items依序回傳 (鍵, 值) 這樣的元組。遍歷字典時,常見的固定寫法是 for k, v in d.items(),用2個變數接收。若把3者的角色互換記憶,就會變成keys回傳值這樣的說明。items回傳的是項目的排列,並非個數,因此「回傳項目數」的說明也是錯誤的,若想知道個數要使用len。順帶一提,若直接把字典傳給for,取出的會是鍵。
練習:作答本頁的題目 這是隨機出題的練習工具(在啟用 JavaScript 時運作)。即使不使用此工具,也能閱讀上方的所有題目與解說。
※ 解說是供學習用的資訊。考試的出題範圍與制度每年可能變動,請務必確認主辦機構的官方公告。
本頁面譯自日文原文。若譯文與原文內容不一致,以日文版為準。 查看日文原文