# 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` `資料分析`