跳到主要內容

Python筆記(5)-串列(list)、元組(tuple)與迴圈

 5-1 串列(list)的操作

我們之前有說明過我們通常會用變數來儲存資料,但有時我們資料量很大的時候,不可能會用很多變數儲存,在操作上會非常不方便,如此就需要有一種資料型態特別用來存取大量資料,在Python中稱為串列(list),在其他程式語言則稱為陣列(Array)。list的語法用[]表示,[1,2,3]則代表此串列儲存3筆數據,data=[1,2,3]則是將串列[1,2,3]指定給data變數,也就是說data代表[1,2,3]以下我們說明list的一些基本操作方法:

程式碼

#list的基本操作方式

numList=[-1,-2,-3,0,1,2,3]        #list元素皆為數值

strList=["Jacky","John","Jimmy"]  #list元素皆為字串

print("numList1的元素:{}".format(numList[0]))

print("numList2的元素:{}".format(numList[1]))

print("strList3的元素:{}".format(strList[2]))

print("numList倒數第1的元素:{}".format(numList[-1]))

print("strList倒數第2的元素:{}".format(strList[-2]))

print("numList2~4的元素形成的子串列:{}".format(numList[1:4]))

print("numList倒數第5~最後一個元素形成的子串列:{}".format(numList[-5:]))

print("numList1~7的元素取出間隔為2的元素形成的子串列:{}".format(numList[0:7:2]))

Python畫面

5-2 串列的進階操作

接下來我們將介紹一些常用的串列相關函數,有助於大數據的整理與分析。

程式碼

#list的進階操作

list1=[2]

list2=list1*10

print("102的串列:{}".format(list2))

print("list2的長度(元素個數):{}".format(len(list2)))

print("="*30)

list3=[-2,10,2,-4,7,0,1,2,7,7]

print("list3的最大元素:{}".format(max(list3)))

print("list3的最小元素:{}".format(min(list3)))

print("list32的索引值:{}".format(list3.index(2)))

print("list3中第22的索引值:{}".format(list3.index(2,list3.index(2)+1)))

print("list37的個數:{}".format(list3.count(7)))

print("list311的個數:{}".format(list3.count(11)))

print("="*30)

list4=["a","b","c","d","e"]

list5=["Jacky","John","Jimmy"]

list4.append("@")

print("list4的最後面插入元素@:{}".format(list4))

list4.insert(3,"#")

print("list4的第4個位置插入#:{}".format(list4))

list4.extend(list5)

print("list4的最後面插入list5:{}".format(list4))

list4.pop()

print("移除list4的最後一個元素:{}".format(list4))

list4.remove("@")

print("移除list4@的元素:{}".format(list4))

list4.remove("%")

print("移除list4%的元素:{}".format(list4))

del list4[2:5]

print("移除list4中位置2到位置4的元素:{}".format(list4))

del list4[0::2]

print("list4位置0到最後一個元素中每次間隔2將元素移除:{}".format(list4))

print("="*30)

list6=["a","b","c","d","e","d","f"]

list7=[-2,10,2,-4,7,0,1,2,7,7]

list6.reverse()

print("list6反轉:{}".format(list6))

list7.sort(reverse=True)

print("list7由大排到小:{}".format(list7))

Python畫面

我們已經了解了串列進階的函數,我們可以利用這些函數,來進行簡單的文本分析,也就是說,給定一篇文章,計算每個單字出現的次數,我們現在就來操作這個例子,英文短文範例如下:

Enjoy that uniquenesss1. You do not have to pretend in order to seem more like someone else. You do not have to lie to hide the parts of you that are not like what you see in anyone else.

You were meant to be different. Nowhere, in all of history, will the same things be going on in anyone’s mind, soul and spirit as are going on in yours right now.

程式碼

#簡易文本分析

artic='''Enjoy that uniquenesss1. You do not have to pretend in order to seem more like someone else. You do not have to lie to hide the parts of you that are not like what you see in anyone else.

You were meant to be different. Nowhere, in all of history, will the same things be going on in anyone’s mind, soul and spirit as are going on in yours right now.

'''

artic=artic.lower()           #將所有單字都變為小寫

artic=artic.replace("\n", "")    #移除\n符號

artic=artic.replace(",", "")     #移除,符號

artic=artic.replace(".", "")     #移除.符號

vocabulary_list=artic.split(" ")  #將文章切割為單字串列

print("切割後的單字串列:{}".format(vocabulary_list))

quire=input("請輸入要查詢的單子...")

print("您查詢的單字為{},出現的個數為{}".format(quire,vocabulary_list.count(quire)))

Python畫面


5-3 多維度串列

多維度串列的意思就是串列中的元素仍是串列,此種結構有助於表示數學中的矩陣,亦可表示多欄位的資料表,以下我們用簡易的範例進行說明。

<範例>請用串列表示以下矩陣

程式碼

#矩陣表示

mat1=[[2,3,1],[0,1,-2],[-4,0,3]]

print("用串列表示的矩陣結構:{}".format(mat1))

print("矩陣第2列第3行的元素:{}".format(mat1[1][2]))

Python畫面

程式碼

#資料表表示

datatable=[["王曉明",98,60,71],["陳大文",100,100,98],["張安安",60,70,72]]

print("{:6s}{:6s}{:6s}{:6s}".format("姓名","國文","英文","數學"))

print("{0[0]:6s}{0[1]:<8d}{0[2]:<8d}{0[3]:<8d}".format(datatable[0]))

print("{0[0]:6s}{0[1]:<8d}{0[2]:<8d}{0[3]:<8d}".format(datatable[1]))

print("{0[0]:6s}{0[1]:<8d}{0[2]:<8d}{0[3]:<8d}".format(datatable[2]))

Python畫面


5-4 元組(tuple)操作

元組的結構與串列完全相同,但主要差異點在於元組的資料不能被修改而串列可以,故元組也被稱為不可修改的串列。之前說過串列主要用[]表示,而元組則是用()表示。

程式碼

#tuple的操作

tuple1=(-2,10,2,-4,7,0,1,2,7,7)

print("tuple8的元素個數:{}".format(len(tuple1)))

print("tuple8中的7的個數:{}".format(tuple1.count(7)))

print("tuple83個元素:{}".format(tuple1[2]))

print("tuple82~5個元素形成的子元組:{}".format(tuple1[1:5]))

Python畫面

我們剛剛說tuplelist的差異在於tuple不可改變內容而list可以,以下就舉幾個簡單例子說明一下,在下面的例子中,我們嘗試修改tuple中元素的值與在tuple中新增新的值,結果都會得到error message

程式碼

#tuplelist的差異(1)

list_test=[1,2,3,4,5]

tuple_test=(1,2,3,4,5)

list_test[0]=100      #list_test第一個元素修改為100

print("修改後的list_test:{}".format(list_test))

tuple_test[0]=100     #tuple_test第一個元素修改為100

print("修改後的tuple_test:{}".format(tuple_test))

Python畫面

程式碼

#tuplelist的差異(2)

list_test=[1,2,3,4,5]

tuple_test=(1,2,3,4,5)

list_test.append(100)      #list_test新增元素100

print("修改後的list_test:{}".format(list_test))

tuple_test.append(100)    #tuple_test新增元素100

print("修改後的tuple_test:{}".format(tuple_test))

Python畫面

5-5 for迴圈的基礎操作

迴圈是程式撰寫中非常重要的一個技巧,他可以快速執行重複性的工作,使得不需要寫很多結構相同的程式碼,在程式的維護上也相對容易許多,但對於初學者在學習程式時,要讓程式重複執行相同的工作,第一直覺就是將程式碼一直複製,雖然這種作法一樣可以達到相同的結果,但是屬於沒有效率的程式撰寫方式,因為程式碼若需要一點修改,可能每一行程式都要修改,這將導致程式維護不易。在迴圈的操作上,最常見的就是for迴圈與while迴圈,後續我們會好好介紹這兩個迴圈的撰寫方式與差異。一開始我們先介紹for迴圈,for迴圈的程式結構如下:

for 變數 in 串列:

程式區塊

我們用以下簡易範例說明:

程式碼

#for迴圈操作(1)

import time

for i in [1,2,3,4,5]:

    print("現在取得的i的值為{}".format(i))

    print("正要返回for敘述取得下一個i")

    time.sleep(1)  #程式執行延遲1

print("<<串列中的值已皆拜訪過一次,結束迴圈!>>")

Python畫面

說明一下這個簡易的例子,for迴圈在執行時,會拜訪串列中每個元素,而元素會被指定給變數(這裡我們把變數命名為i),然後進入程式區塊執行程式,這邊要特別注意,程式區塊必須要縮排,否則會出現錯誤訊息。這邊因為程式過於簡單,執行速度會非常快就結束(不到一秒),所以為了讓讀者感受for迴圈的工作,我們在一開始先引進一個time套件(語法:import time),想藉由time套件中的time.sleep(秒數)這個函數,讓程式執行時中間有延遲的效果,讀者可更清楚for迴圈的執行模式。

大多數學習for迴圈時,第一個挑戰的題目就是,計算1+2+3+…+10,我們都知道是55,但如何用撰寫程式的方式得到答案,卻是一個學習程式過程中必經之路,通常初學者會很有耐心的寫1+2+3+4+5+6+7+8+9+10,然後執行程式得到正確答案,但這種寫法就是我們所說的沒有效率的寫法,今天如果將1加到10改成1加到100還是要這樣寫嗎? 讀者可以思考一下? 我們以下用for迴圈解決這個問題。

程式碼

#for迴圈操作(2)

Sum=0

for i in [1,2,3,4,5,6,7,8,9,10]:

    Sum=Sum+i

print("<<迴圈結束!>> Sum值為{}".format(Sum))

Python畫面

這裡用到將Sum值更新的寫法,Sum=Sum+i,第一次i取得為1時,進到程式區塊後Sum+i就是0+1,結果為1在指定回Sum,所以這時候Sum被更新為1(1);第二次i取得為2時,進到程式區塊後Sum+i就是1+2,結果為3在指定回Sum,所以這時候Sum又被更新為3(1+2); 第三次i取得為3時,進到程式區塊後Sum+i就是3+3,結果為6(1+2+3)指定回Sum,所以這時候Sum再次被更新為6了,依此類推,最後Sum值會被更新到55,也就是1+2+3+…+10的結果。

但相信有讀者會發現,如果1+2+3+…+100,上面寫法也有些瑕疵,串列部分難道要寫成[1,2,3,4,5,…,100]沒錯,當然不可以這樣寫,這樣寫就落入我講的沒有效率,所以有沒有什麼現有的函數可以直接得到連續整數的串列,答案是有的,這個函數叫做range(),以下我們先簡單說明range()的用法,再將上面的程式優化。

程式碼

#range()相關用法

print("0~10連續整數的串列:{}".format(list(range(11))))

print("1~10連續整數的串列:{}".format(list(range(1,11))))

print("1~10中間隔為2的整數串列:{}".format(list(range(1,11,2))))

print("-10~10連續整數的串列:{}".format(list(range(-10,11))))

print("10~1連續整數的串列:{}".format(list(range(10,0,-1))))

print("10~1中間隔為2的整數串列:{}".format(list(range(10,0,-2))))

Python畫面

學會了range()的用法,我們就可以將這個問題一般化,即1+2+3+…+n的值,我們現在就來將上面的程式進行小小修改,就可以解決任何n值的問題。

程式碼

#for迴圈操作(3)

n=int(input("請輸入n值,計算1~n的總和..."))

Sum=0

for i in range(1,n+1):

    Sum=Sum+i

print("<<迴圈結束!>> 1~{}的總和為{}".format(n,Sum))

Python畫面

再給大家一個練習題,將上面的程式做一點小修改,計算n!(n階乘)的值,我將我的寫法寫在下面給讀者參考,大家可先思考看看如何修改。

程式碼

#for迴圈操作(4)

n=int(input("請輸入n值,計算n!的值..."))

prod=1

for i in range(1,n+1):

    prod=prod*i

print("<<迴圈結束!>> {}!的值為{}".format(n,prod))

Python畫面

前面介紹for迴圈都是在操作數值的資料型態,我們將前面的一個文本分析的例子進行推廣,列出所有出現的單字,並計算出現次數,並用表格呈現,大家可以想想如何撰寫,我將我的寫法寫在下面給大家參考。

程式碼

#簡易文本分析(2)

artic='''Enjoy that uniquenesss1. You do not have to pretend in order to seem more like someone else. You do not have to lie to hide the parts of you that are not like what you see in anyone else.

You were meant to be different. Nowhere, in all of history, will the same things be going on in anyone’s mind, soul and spirit as are going on in yours right now.

'''

artic=artic.lower()            #將所有單字都變為小寫

artic=artic.replace("\n", "")  #移除\n符號

artic=artic.replace(",", "")   #移除,符號

artic=artic.replace(".", "")   #移除.符號

vocabulary_list=artic.split(" ") #將文章切割為單字串列

vocabulary_list_Nondup=[]      #移除重複出現的單字       

print("{:<12s}{:<4s}".format("單字","出現次數"))

for v in vocabulary_list:

    if v not in vocabulary_list_Nondup:

        vocabulary_list_Nondup.append(v)

        print("{:<14s}{:<4d}".format(v,vocabulary_list.count(v)))

Python畫面

我們最後再給一個例子,這個例子會用大量的forif敘述,正好將前面學過的再複習一次。我們建立一個成績登入系統,可以自由設定要登入多少位學生的成績,登入完成後,自動計算等級與平均分數並印出報表。

程式碼

#成績登入系統

print("成績登入系統".center(30,"="))

N=int(input("請輸入學生人數:"))

print("="*30)

sd_name=[];math_score=[];english_score=[]

for i in range(N):

    sd_name.append(input("請輸入第"+str(i+1)+"位學生姓名:"))

    math_score.append(float(input("請輸入該生數學成績...")))

    english_score.append(float(input("請輸入該生英文成績...")))

    print("-"*20)

print("學童成績表".center(40,"="))

print("{:<8s}{:<8s}{:<8s}{:<8s}{:<8s}".format("學生姓名","數學成績","英文成績","總平均","等級"))

for i in range(len(sd_name)):

    ave=(math_score[i]+english_score[i])/2

    if   ave>=90:

        grade="A"

    elif 80<=ave<90:

        grade="B"

    elif 70<=ave<80:

        grade="C"

    else:

        grade="D"

    print("{:<11s}{:<12.2f}{:<11.2f}{:<11.2f}{:<1s}".format(sd_name[i],math_score[i],

english_score[i],ave,grade))

Python畫面

5-6 for迴圈的進階操作

for迴圈的進階操作中,我們將介紹巢狀for迴圈,也就是進入for迴圈的程式區塊後還有for迴圈需要執行,以下我們用兩個例子來介紹如何撰寫巢狀for迴圈,第一個範例是印出99乘法表,第二個範例是執行矩陣乘法。

程式碼

#印出九九乘法

print("九九乘法表".center(82,"="))

for i in range(1,10):

    for j in range(1,10):

        print("{:<1d}*{:<1d}={:<2d}".format(j,i,j*i),end=" |  ")

    print()

Python畫面

程式碼

#執行兩個3*3矩陣的乘法

matA=[]

for i in range(1,4):

    matA_row=input("請輸入A矩陣第{}列:(數字請以,隔開)".format(i))

    matA.append(list(map(int,matA_row.split(","))))

print("矩陣A:{}".format(matA))

print("-"*40)

matB=[]

for j in range(1,4):

    matB_row=input("請輸入B矩陣第{}列:(數字請以,隔開)".format(j))

    matB.append(list(map(int,matB_row.split(","))))

print("矩陣B:{}".format(matB))

AB=[]

for row in range(3):

    rowlist=[]

    for col in range(3):

        prodsum=0

        for x in range(3):

            prodsum=prodsum+matA[row][x]*matB[x][col]

        rowlist.append(prodsum)

    AB.append(rowlist) 

print("="*40)

print("A*B={}".format(AB))

Python畫面

在矩陣乘法的例子中,我們有用到一個map()函數,在這裡主要是把串列中的數值字串轉成數值資料型態,才能做後續的數字乘法。我們可以參考以下網站了解map()函數的用法(https://www.runoob.com/python/python-func-map.html)


5-7 break continue的使用

有時候我們會想中斷迴圈或跳過就可使用breakcontinue的語法,break會直接結束迴圈的執行,continue則是會直接跳過寫在continue以下的程式碼,會直接回到迴圈最上層,取下一個串列值再繼續往下執行。以下我們分別個給一個範例進行說明。

程式碼

#質數判斷器

n=int(input("請輸入一個大於1的正整數..."))

for i in range(2,round(n**(1/2))+1):

    if n%i==0:print("{}不是質數!".format(n));break

else:print("{}是質數!".format(n))

Python畫面

我們這邊的for迴圈之後加了一個else,當break發生for迴圈結束,不會執行else的部分,如果不使用else,直接寫print("{}是質數!".format(n)),當break發生for迴圈結束時,會一併執行print("{}是質數!".format(n)),會出現是質數又不是質數的窘境。

程式碼

#樓層命名-(不含4)

n=int(input("請輸入樓層數..."))

print("樓層名稱為:",end="")

for i in range(1,n+2):

    if i==4:

        continue

    print(i,end=" ")

Python畫面

5-8 while 迴圈的操作

常用的迴圈有兩種,for迴圈與while迴圈,這兩者最大的差異是for迴圈的執行次數是已知的,while迴圈則是可以用於已知與未知的狀況下,原因是他在執行時是用條件是進行判斷,以下是while迴圈的結構:

while 條件式:

程式區塊

也就是說,滿足條件式,則進入程式區塊執行程式,如不滿足,則結束while迴圈。以下我們用幾個例子,說明一下while迴圈的操作。

程式碼

#while的操作(1)

s=0

while s<30:

    num=int(input("請繼續輸入數字,直到總和大於等於30即結束..."))

    s=s+num

print("所有的數字總和為:",s)

Python畫面

程式碼

#while的操作(2)

print("計算根號2的近似值".center(30,"="))

a=1;b=2

accuracy=b-a

while(accuracy>0.0001):

    m=(a+b)/2

    if(m**2>2):

        b=m

    else:

        a=m

    accuracy=b-a

print("根號二介在{:.5f}~{:.5f}".format(a,b))

Python畫面

程式碼

#while的操作(3)

sentence="an apple a day keeps the doctor away"

print("原始句子:",sentence)

s_list=sentence.split()

word=input("請輸入你要查詢的單字(輸入-1即跳出查詢):")

while (word!="-1"):

    if word in s_list:

        print("文章中\"存在\"此單字...")

        print("="*30)

    else:

        print("文章中\"不存在\"此單字...")

        print("="*30)

    word=input("請輸入你要查詢的單字(輸入-1即跳出查詢):")

print("結束查詢....")

Python畫面

在使用while迴圈時要特別注意條件式的寫法,如果條件式總是True,會形成無窮迴圈,程式會一直執行停不下來,宛如當機的狀態,此時可以按Ctrl + C中斷程式,檢查程式的問題點,修改後再重新執行一遍。

留言

這個網誌中的熱門文章

RPA-Uipath筆記(1) - 如何從網路上下載資料並存至指定路徑

最近在做 RPA 相關專案時遇到了這個問題: 如何從網路上下載資料並存至指定路徑? 針對這個問題我們採取的解決方案是 先讓檔案下載到電腦的預設路徑,再將檔案移動到我們指定的資料夾 。 以下我們用下載政府公開資料平台的資料 ("https://data.gov.tw/dataset/116285") 為例, Uipath 的流程建立如下: 使用到了 Wait for Download 、 Move File 、 Delete File 三個 Activity , Wait for Download 中 Monitored folder 必須放瀏覽器中設定的下載檔案的預設路徑且關閉詢問儲存位置。 Downloaded file 則是設定一個變數名稱 downloadfile( 可自訂 ) ,此變數的資料型態是 FileInfo 。中間則放入下載的流程步驟,從下載開始到結束都會在此 Activity 中執行完畢,執行完後所下載的檔案的相關資訊都會被存放在變數 downloadfile 中。 接下來是將檔案從預設下載路徑中移至指定路徑,這裡就需要下載預設路徑與指定路徑,這兩個我們在流程一開始就建了了兩個變數 dnlo_path 、 asng_path ,寫法如下: dnlo_path = "C:\Users\" +system.Environment.UserName+ "\Downloads" system.Environment.UserName à VB 語法,代表目前電腦的使用者名稱。 asng_path = "D:\Bolg 資料 \Uipath\Uipath(1)" Move File Activity 中 From 要放入目前檔案的位置; To 則要放入檔案存放的指定的位置,但因為是要做檔案的移動,所以以上兩個路徑後面都要再加上檔案名稱,這時可以使用 downloadfile 這個變數的屬性值叫出檔案名稱( downloadfile.Name ),當檔案名稱是隨機變動的時候,非常好用。另外,特別值得注意的是, To 的部分在加上檔案名稱時,可以不用用原始檔案的名稱,這時可以同時達到修改檔名的效果。 Overwrite 的部分打勾代表再重複執行一次的時...

RPA-Uipath(2) - 字串分割(String.Split())與合併(String.join())

在資料清理中,我們常常需要對字串進行分割或合併,今天來簡單介紹 Uipath 中字串如何進行分割與合併。 1.      字串分隔 ( 單一分割符號 ) 我們首先建了一個字串變數 Str1= "Jimmy,Johnson,Shawn,Alan,Nick" ,我們現在想把這些人名一個一個切割出來,很明顯只要將 ”,” 作為分個符號就可以了。這邊我們建立一個陣列變數 Str1_Array=Str1.split(","c) ,這個陣列變數就會儲存分割出來的結果。我們接下來用 For each 與 Write Line 將陣列的每一項內容印出來,就可以知道我們分割的結果有沒有成功。 2.      字串分隔 ( 多個分割符號 ) 我們首先建了一個字串變數 Str2= "Jimmy,Johnson.Shawn Alan,Nick" ,我們現在想把這些人名一個一個切割出來,很明顯要將 ”,” 、 ”.” 、 ” “ 都作為分個符號才能完整分割。這邊我們建立一個陣列變數 Str2_Array= Str2.Split(",|.| ".ToArray()) or Str2.Split({","c,"."c," "c}) ,這個陣列變數就會儲存分割出來的結果。我們接下來用 For each 與 Write Line 將陣列的每一項內容印出來,就可以知道我們分割的結果有沒有成功。 3       字串的合併 (Array 字串元素合併 ) 我們首先建了一個字串變數 Str3_Array= {"John","Jimmy","Shawn","Alan"} ,我們現在想把這些人名中間用 ”|” 符號隔開並且變成一個字串,這裡我們是用 String.Join( 連接符號 , 陣列 ) 這個函數達到這個目的。我們建立一個變數 Str3_Join ,使 Str3_Join=String.Join("|", Str3_Array) ,此時 Str3_Join 的結果就會是 John|Jimmy|Shawn|Alan 。我們接下來用 Write...

RPA-Uipath(5)-如何讀取Mail與取得Mail的資訊

本篇主要介紹 Uipath 取得 mail 相關資訊與附件的方法,因為 mail 的種類眾多,本範例以 Gmail 為例。首先在使用 Uipath 取得 Gmail 相關資訊前須對 Google 帳戶的安全性進行兩階段驗證設定,設定方式如下: Step1. 點選 ” 管理你的 Google 帳戶 ” Step2.  點選 ” 安全性 ” à ” 兩階段驗證 ” à 點選 ” 開始使用 ” Step3.  依 Google 所提示步驟,您最後會取得一組密碼,請務必將此密碼記下。 接下來要開始使用 Uipath 擷取 mail 相關資訊,一開始我們先使用 Get Password 儲存 mail 登入的密碼,此時密碼不是使用您真正的密碼而是使用剛剛兩階段驗證後取得的密碼,並儲存於變數 password 。 接下來使用 Get IMAP Mail Messages 來取得 mail 的相關資訊,在使用 Get IMAP Mail Messages 時必須在其屬性設定區塊進行一些參數設定。 Port 欄位填入 993 , Server 欄位填入 "imap.gmail.com" , Email 欄位填入您的 Email , Password 欄位填入 變數 password , Message 欄位我們用 MailMessage 變數填入 Mail 的相關資訊都會存在 MailMessage 變數中,我們可以用 For Each 迴圈逐一取得 mail 的相關資訊。 For Each 的屬性區塊部分也需要進行一些參數設定, List of item 欄位需填入 MailMessage 變數, TypeArgument 則須設定為 System.Net.Mail.MailMessage 。 設定完成後,我們先用 Write Line 將信件的主旨印出做為測試( 這邊我們只印出前 5 封信件的主旨,可在 Get IMAP Mail Messages 的屬性區塊中 Top 欄位中設定 ),如果要印出信件主旨,需要用 item.Subject 屬性,如要印出其他資訊,我們將常用的幾個列在以下表格: 最後,有些信件會附帶一些附件,我們如何將這些物件儲存下來呢 ? 這邊只需要用到 Save Attachments 即可。我們將其放在迴圈內以下載每個有附件的 mail...