---
# System prepended metadata

title: 3/26 Python與資料分析#4 - 函數
tags: [python, 資料分析]

---

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