###### tags: `python` # 函數 ## 特性 * 將重複撰寫的程式碼以函數的架構重新整理 * 給予這段程式碼一個有意義的名稱(函數名稱) * 當要使用該功能時呼叫該函數即可 * 可以讓程式更加簡潔、意義化、可重複使用、降低錯誤率、方便維護 ## 函數來源 * 語言內建: print(), input(), type() ... * 第三方模組/函數庫: wxPython, matplotlib ... * 自行開發 ## 注意 * 函數必須先定義才能呼叫 ---- ## 範例一: 無參數、無回傳值 ```python= def showMsg(): # 定義有個函數叫showMsg print("hello") showMsg() # 呼叫showMsg函數 ``` ## 範例二: 無參數、有回傳值 ```python= count = 0 def counts(): global count # 使用全域變數 count = count + 1 return count print(counts()) print(counts()) ``` ## 範例四: 有參數、無回傳值 ```python= def showMsg(funName): print('run function: ', funName) showMsg('add') showMsg('sub') ``` ## 範例四: 有參數、有回傳值 ```python= def add(num1, num2): return num1 + num2 result = add(3, 6) print("result =", result) # result = 9 result = add(32, 26) print("result =", result) # result = 58 ``` ---- ## 參數傳遞方式 ### 傳值呼叫 預設傳值: 數值、字串、tuple ```python= def swap(x, y): print('x = {0}, y = {1}'.format(x, y)) x, y = y, x print('x = {0}, y = {1}'.format(x, y)) a, b = 1, 2 print(a, b) swap(a, b) print(a, b) # swap並沒有改變a, b的值 ``` ### 傳址呼叫 預設傳址: list(串列), set(集合), dict(字典) ```python= def swap(x): print('x[0] = {0}, x[1] = {1}'.format(x[0], x[1])) x[0], x[1] = x[1], x[0] print('x[0] = {0}, x[1] = {1}'.format(x[0], x[1])) x = [1, 5] print(x[0], x[1]) swap(x) print(x[0], x[1]) # swap改變x的內容順序 ``` ## 關鍵字參數 沒有指定照傳入順序,有指定照指定設定 指定參數必須放在無指定參數的後面 ```python= def showMsg(person1, person2): print('{0} 喜歡 {1}'.format(person1, person2)) showMsg('小明', '小華') showMsg(person2='小明', person1='小華') showMsg('小華', person2='小明') # 正確 showMsg('小華', person1='小明') # 錯誤,person1已經被指定微小華 showMsg(person2='小明', '小華') # 錯誤,無指定參數必須放在指定參數之前 ``` ```python= str1 = '{0} love {1}' str2 = '{0} like {1}' print(str1) print(str2) str3 = str1.format('amos', 'carol') str4 = str2.format('amos', 'carol') print(str3) print(str4) str5 = '{name} is {year} old {name}' str6 = str5.format(name='amos', year=18, gen='man') print(str5) print(str6) ``` ## 參數預設值 當沒有指定參數值時使用預設值 ```python= def add(x, y=10): return x+y print(add(5, 12)) print(add(5)) ``` ## 任意參數數量 ```python= def add(*num): # 將多個打包成一個 total = 0 for i in num: total += i return total print(add(3)) print(add(3, 5)) print(add(3, 5, 112)) # ----------------------------- def add(num1, num2, num3, num4, num5): return num1 + num2 + num3 + num4 + num5 data = (3, 5, 9, 10, 15) print( add(*data) ) # 將一個拆成多個 # add(data[0], data[1], data[2], data[3], data[4]) ``` ## 任意字典參數數量 ```python= def intro(id, name, years, location): msg = ''' 編號: {0} 姓名: {1} 年資: {2} 廠區: {3}'''.format(id, name, years, location) print(msg) intro(1, 'amos', 10, 'taipei') one = [1, 'amos', 10, 'taipei'] # intro(one[0], one[1], one[2], one[3]) intro(*one) two = {'id': 1, 'name': 'amos', 'years': 10, 'location': 'taipei'} # intro(two['id'], two['name'], two['years'], two['location']) intro(**two) ``` ```python= def intro(**info): msg = ''' 編號: {0} 姓名: {1} 年資: {2} 廠區: {3}'''.format(info['id'], info['name'], info['year'], info['location']) print(msg) intro(id=1, name='amos', year=10, location='taipei') ``` ## 三種參數種類使用順序 **必須遵守以下順序:** **參數, 任意數量, 任意字典參數** ```python= def info(name, *args, **kwargs): print('name: ', name) for i in args: print(i) for key, value in kwargs.items(): print('{0} = {1}'.format(key, value)) info('amos', '111', 'taipei', language='python', DB='mySQL') # name: amos # 111 # taipei # language = python # DB = mySQL ``` ---- ## 區域變數, 全域變數 ```python= num1 = 5 num2 = 5 def add(): num1 = 10 print('在函數中的num1: ', num1) global num2 num2 += 30 print('在函數中的num2: ', num2) print('在函數外的: ', num1) print('在函數外的: ', num2) print('===========================') add() print('在函數外的: ', num1) print('在函數外的: ', num2) ``` --- ## 匿名函數(lambda) * 當有些函數本身非常簡單,只有一個運算式 * 該函數使用頻率很低 * 讓程式碼更簡潔(但執行效能不變) * 函數內容只能放**運算式**,不能放**指派運算式**(例如: x=5) * 通常與**map、reduce、filter**函數一起使用 ```python= def sum(num1, num2): return num1+num2 print(sum(10, 5)) ``` ```python= sum = lambda num1, num2: num1 + num2 print(sum(10, 5)) ``` ## 匿名函數範例 ```python= pern = [ ('Mary', 1988, 'taipei'), ('Davie', 1992, 'kaohsiung'), ('Andy', 1999, 'taichung') ] st = lambda item: item[0] i = pern[0] # ('Mary', 1988, 'taipei') j = st(i) # 'Mary' print(j) pern.sort(key = st) for name in pern: print('{0}, {1}, {2}'.format(*name)) ``` ## 用python來寄信 ```python= import smtplib sender = 'wootu.test@gmail.com' # 你的gmail帳號 sender_password = '' # 你的gmail密碼 receivers = ['amos.tsai@gmail.com'] # 要寄給哪些人 message = """From: From Person <from@fromdomain.com> To: To Person <to@todomain.com> Subject: SMTP e-mail test This is a test e-mail message. """ # 信件內容 smtpObj = smtplib.SMTP('smtp.gmail.com', 587) smtpObj.ehlo() smtpObj.starttls() smtpObj.ehlo() smtpObj.login(sender, sender_password) smtpObj.sendmail(sender, receivers, message) smtpObj.quit() ``` ## 參考資料 [關於python*和**的問題](https://github.com/dokelung/Python-QA/blob/master/questions/star/關於python*和**的問題.md)