# 3/26 Python與資料分析#4 - 函數 ## 目的 組織並封裝程式碼、命名,以便之後可以一直使用並可慢慢規模化,維護也較容易 ## 種類(規模由小到大) Functions Classes Modules Libraries 規模小的可以打包到規模大的,Library甚至可以打包成更大的 # Function ## 基本架構 函數:映射關係 def 自訂函數名稱(參數) return 結果 ``` def function_name(INPUTS, ARGUMENTS, ...): """ docstring: print documentation when help() is called """ # sequence of statements return OUTPUTS ``` 呼叫:直接輸入函數名稱(參數) ### 多對一(輸入不只一個) 若數量固定,可以用多個參數或是陣列 例如 def abc(x, y) 如果return有兩個變數,預設是tuple呈現,也可以自訂(要自己寫) 若數量不固定,可利用*args或**kwargs(包含key value) 或用陣列+迭代解決(參數是list,輸入元素數量則沒有限制) * 陣列舉例:(此x是陣列,用for去遍尋) ``` def prod(x): a = 1 for i in x a = a*i return a ``` * *args:用Tuple呈現 def abc(*args) 就可以輸入不定量的tuple了(例如(1,2,3,4)或(6,7,8)) 但利用的時候一樣可以用for迭代 變數名稱是args * *kwargs:用Dictionary呈現 def abc(*kwargs) 就可以輸入不定量的dict了(例如(a=1, b=2, c=3)) 但利用的時候一樣可以用for迭代 變數名稱是kwargs ## 可能的Error * Syntax Errors: 語法錯誤 使用了Python沒有的方法(例如沒有縮排) * Runtime Errors: 直譯/執行錯誤 Name Error 找不到物件(例如函數) Type Error 運算不符合該物件的類型(例如str減int) ZeroDivision Error 除以0 Index Error 出現錯誤的index * Semantic Errors: 語意錯誤 邏輯上錯誤,或是沒執行錯誤但得出非預期的結果 ### Try Except ``` Using try and except to catch exceptions try: # sequence of statements if everything is fine except TYPE_OF_ERROR: # sequence of statements if something goes wrong ``` try: 某程式碼 except Type_of_error 可以輸入錯誤類型,也可以不輸入表示任何錯誤 如果執行錯誤的話就會發生後面寫的事 except可以寫多次,類似if elif 純except類似else 這樣可以讓程式不因為錯誤而停止運行 ## 變數的Scope Local / Global 變數只要離開函數的框架(縮排內),預設就會變成Name Error (Local Variable) 若最外面就宣告此變數,就可以避免這個問題 尋找變數的時候,以該區域為優先,找不到再往外找 不建議內外都有一樣變數造成混淆 ## List Comprehension Python可以在建構list的時候加上描述,直接建構 例如: primes = [2,3,5,7] p = [i**2 for i in primes] 可以直接把p裡面的元素平方 若還需要加上判斷式則可添加if p = [i**2 for i in primes if i>3] 甚至可以多個判斷 p = [True if i >2 False if i<2 for i in primes] Python 3之後有set/dict comprehension ## Generators 一段建構的敘述但還沒生成(可以想成模具) ``` primes = [2, 3, 5, 7, 11] squared_primes = (p**2 for p in primes) print(squared_primes) print(type(squared_primes)) print(list(squared_primes)) ``` squared_primes只是一行敘述 前兩行會得到 <generator object <genexpr> at 0x7f8e32d36430> <class 'generator'> 第三行才會得到包含符合條件的list generator只能使用一次,若再輸入print(set(squared_primes))則會出現空白 ## Iterator 只能用一次(節省記憶體) 常見的: range() enumerate() zip() map() filter() reduce()(python3之後變成標準函數) ### enumerate() enumerate is useful for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ... 類似generator,emuerate得到的是一個敘述 如果要實體化,可以用list(enumerate(x))得到 如果沒有實體化,直接print(enumerate(x))會得到 <enumerate object at 0x7faea5d2cdc0> ### zip() list(zip('abcdefg', range(3), range(4))): [('a', 0, 0), ('b', 1, 1), ('c', 2, 2)] 針對幾個字串或可迭代對象或list,得到n組平行一個對一個的tuple,可用list/tuple呈現(n為全部資料裡面資料數最少的) 可將同位置資料串接 ### map() map(func, *iterables) --> map object ``` print(map(float, range(10))) print(list(map(float, range(10)))) ``` 得到 <map object at 0x7faea5c96a30> [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] 前面的函數func對後面的可迭代物件每個元素分別作用 (functional function) 若要呈現可用list/tuple ### filter() filter(function or None, iterable) --> filter object 若填None,則只留下True map或filter的func的部分常常搭配lambda函數表示 `lambda x: x*10` 代表把x都乘以10,可用在map上 (輸入:輸出) `lambda x: x>=10` 代表大於等於10都會輸出True,可用在filter上 ### reduce() from functools import reduce 才能用 reduce(function, sequence[, initial]) -> value 將一群數列運算變成一個數值 function若為add,則將數值相加... 以上都可以用for來遍尋 例如 for a,b in zip(a1,a2) 並可善用 {} {} .format(a,b) ###### tags: `python` `資料分析`