遞迴
在這裡,我們要舉一個稍微複雜的例子,目的是除了講解函式之外,還帶給讀者們一些其他的重要觀念。
還記得我們講過的巢狀結構嗎:
lst = [1, 2, [3, 4, 5], 6, [7, [8, 9]]]
假設我今天想要把裡面的每個元素 (不管這個元素在第幾層了) 都列印出來,該怎麼做呢?我們先試試看這樣:
for item in lst:
print(item)
會得到這樣的結果:
1
2
[3, 4, 5]
6
[7, [8, 9]]
顯然不是我們想要的,當我們發現元素是清單的時候,應該要再次迭代該清單的項目:
for item in lst:
if isinstance(item, list):
for item2 in item:
print(item2)
else:
print(item)
isinstance
是一個內建函數,可以幫助我們判斷變數的型態,他需要兩個參數,第一個是要測試的資料,第二個是指名要確認的形態,isinstance(data, type)
的意思就是問 data
是 type
型態的嗎?isinstance(item, list)
就是問 item
是 list
型態的嗎?
這樣我們可以在元素為清單時,再次迭代,元素不是清單時就直接印出,乍看之下這解決了問題,但是我們卻發現,如果清單位於第二層裡就沒辦法在迭代到了,好了,讀者們會說,那就再度迭代即可,但其實沒有那麼容易,我們並不知道要處理的清單究竟有多少層?
這時候我們只能使用 遞迴 的手法,但首要的工作,我們需要自定義一個函式:
def print_list(lst):
for item in lst:
if isinstance(item, list):
print_list(item)
else:
print(item)
這個函式是這樣的,我們先迭代一次傳進來的清單,若發現某元素是清單,我們便去呼叫自己本身,否則我們直接把元素印出來。
我們會發現,不管清單位於哪一層,只要我們發現他,我們便呼叫 print_list
處理,就好像剝洋蔥一樣,一層一層剝開,我們不需要煩惱要剝幾層,只要知道,若沒有剝到最底的一層,我們便要繼續剝。這就是遞迴的手法,這在程式的世界是很重要的技巧,寫在這裡供讀者體會。