# 2022-11-27 第三天 Python網路爬蟲應用實務班上課記錄
###### tags: `python` `爬蟲`
## 函式
```python=
# 將一組成程式碼集中起來, 可以完成某件事或某個功能, 需要透過"呼叫"的手段來讓函式(或稱為函數)內的程式碼執行
# 1. 函式名稱可以是 數字, 英文大小寫, 底線的組合
# 2. 函式名稱第一個字不可以是數字
# 3. 不可以使用Python保留字
# 4. 可以使用跟內建函式名稱一樣的名字,但你會失去原本函式的功能,所以不建議
# 5. 函式名稱的大小寫視為不同名稱
# 小括號內定義該函式呼叫時要傳入多少個參數, 空的話表示不需要參數(或稱為引數)
def my_first_func():
print('Hi my function')
my_first_func() # 函式呼叫
my_first_func() # 函式呼叫
my_first_func() # 函式呼叫
# 有個參數的函式
def show_me(name): # 定一個呼叫時一定要傳入一個參數的函式
print(f'My name is {name}') # name參數對於show_me函式來說是一個"內部"變數
show_me('Aaron') # 呼叫show_me函式病傳入Aaron字串作為該函式內的name參數
show_me('Andy') # 呼叫show_me函式病傳入Aaron字串作為該函式內的name參數
show_me('Abner') # 呼叫show_me函式病傳入Aaron字串作為該函式內的name參數
# 有兩個參數的函式
def compare_num(a1, a2):
if a1 > a2:
print(f'{a1} 比 {a2} 大')
else:
print(f'{a1} 比 {a2} 小')
compare_num(4, 8) # 參數傳入函式後會被依照參數的順序擺放
compare_num(48, 23)
# 有三個參數的函式
def three_param(a, b, c):
print(f'三個參數為: {a}, {b}, {c}')
three_param('Test', 99, True)
```
#### 練習
```python=
# 寫一函式,名稱為 user_input,該函式功能為:
# 1. 接受使用者輸入一個整數參數
# 2. 將該使用者輸入平方後顯示到畫面上
def user_input(num):
print(f'{num ** 2}')
user_input(20)
user_input(12)
```
#### 參數預設值
```python=
# 參數預設值, 當呼叫函式如果沒有傳入該對應的參數,則直接使用一個預設值作為參數
def show_me(name = '無名氏'):
print(f'My name is {name}')
show_me('Aaron')
show_me()
# 有參數預設值的參數,右邊的參數全部都要有預設值
def check_num(a, b = -1, c = -1):
print(f'{a}, {b}, {c}')
check_num(1, 2, 3)
check_num(1)
# check_num() # 沒有參數預設值就醫定要傳入該參數
check_num(1, 2)
def my_info(name, phone, addr):
print(f'我的名字叫{name}, 電話是{phone}, 家裡地址{addr}')
my_info(phone='0987654321', addr='台北市某個地方', name='Aaron') # 透過指定參數名稱的方式來傳入參數
```
#### 回傳值
```python=
# 回傳值
# 函式在執行結束後可以產生資料回傳給呼叫方
def do_plus(a1, a2):
print(f'總和: {a1 + a2}')
total = a1 + a2
return total # 結束函式執行(類似迴圈內的break),並回傳後面的資料
total = do_plus(2, 3) # 接收函式回傳值
print(f'接受到回傳值: {total}') # 注意: 這個total和函式內的total為兩個不同的變數
# 打算把2 + 3的結果作平方
print(f'2和3加總後的平方為: {total ** 2}')
```
#### pack與unpack
```python=
# 寫一函式swap, 可以用來交換兩個變數內的資料
def swap(a, b):
return b, a # return 永遠只能回傳一筆資料, 這裡會pack兩筆資料成為一個tuple
aa = 99
bb = 88
aa, bb = swap(aa, bb)
print(f'aa = {aa}, bb = {bb}')
c = swap(aa, bb)
print(c, type(c))
# tuple 回憶
a = 3, 4, 5, 6, 7
print(a, type(a))
a, b, c = a # unpack tuple並存到三個變數內
print(a, b, c)
```
#### 一級函式
```python=
# 一級函式
# Python的函式就是一級函式, 函式本身就是一個物件(資料), 可以被存到變數內
def show_me(name):
print(f'My name is {name}')
# a = show_me() 這個是把show_me函式的回傳值存到a變數
a = show_me # 將show_me函式本體存到a變數
a('Aaron')
def do_plus(a, b):
return a + b
def do_miner(a, b):
return a - b
def do_mux(a, b):
return a * b
def do_div(a, b):
return a / b
a = 10
b = 5
print( do_plus(a, b) ) # 一行程式碼有多個函式, 其呼叫順序為由內到外
print( do_miner(a, b) )
print( do_mux(a, b) )
print( do_div(a, b) )
def do_math(do_func, a, b):
return do_func(a, b)
print( do_math(do_plus, a, b) ) # 一行程式碼有多個函式, 其呼叫順序為由內到外
print( do_math(do_miner, a, b) )
print( do_math(do_mux, a, b) )
print( do_math(do_div, a, b) )
```
#### callable()
```python=
# callable() Python內建函式, 用來偵測某個變數內是不是函式, True=是函式, False=不是函式
def show():
print('Show')
a = 2
print( callable(a) )
a = show
print( callable(a) )
if callable(a) == True:
a()
else:
print(a)
```
#### lambda函式
```python=
# LAMBDA 定義函式, 定義出來的函式"只有一行", 而且沒有名字
# def show(a, b):
# print(a, b)
# lambda定義完後可以直接呼叫
(lambda a, b: print(a, b))(2, 'Hi')
# show(1, 'Hi')
# 範例
def max(a1, a2):
# if a1 > a2:
# return a1
# else:
# return a2
return a1 if a1 > a2 else a2
print(max(5, 6))
print(max(15, 9))
print(max(99, 54))
max2 = lambda a1, a2: a1 if a1 > a2 else a2 # 不需要加上return
print(max2(5, 6))
print(max2(15, 9))
print(max2(99, 54))
print(type(max2))
```
#### 拯救內建函式
```python=
# 拯救函式
a = [1, 2, 3, 4, 5]
total = sum(a)
print(total)
b = [3, 4, 5, 6]
sum = 0
for n in b:
sum += n
print('總和為:', sum)
print(type(sum))
del sum # 把sum的功能刪掉(但不會刪掉python內建功能)
total = sum([1, 2, 3]) # 此行會恢復Python內建sum函式的功能
```
#### 練習
```python=
# 練習
# 1. 寫一函式, 名叫 check_score, 可以傳入一個整數參數, 如果數字大於等於60, 則回傳True, 如果小於60, 則回傳False
# 2. 將上一個函式改用lambda來實現
def compare_score(a1):
if a1 >= 60:
return True
else:
return False
a1 = int(input("請輸入分數:"))
if compare_score(a1) == True:
print('及格')
else:
print('不及格')
compare_score = lambda a2: True if a2 > 60 else False
a2 = int(input("請輸入分數:"))
if compare_score(a2):
print('及格')
else:
print('不及格')
```
## 例外(exception)
```python=
# 例外(exception)
# 當程式執行時發生預期外"邏輯錯誤"造成的執行失敗而產生的結果
try:
a = int(input('請輸入一個整數:')) # 當這裡產生例外,接下來同樣在try裡面的程式碼都會被忽略,並跳到except裡面執行
print(f'你輸入了: {a}, 平方值: {a ** 2}')
a /= 0
except ValueError: # 捕捉ValueError例外
print('您輸入了非整數的資料')
except ZeroDivisionError: # 捕捉ZeroDivisionError例外
print('發生除以0的例外')
except Exception as e: # 將所有的例外都捕捉下來, 並將例外物件存到變數e裡面
print('發生例外了:', e, type(e))
else:
print('都沒有例外發生的時候會執行else裡面的程式碼')
finally:
print('不管如何,都一定會被執行')
# 當產生例外時,錯誤訊息的最後一行, 冒號前面的描述即為該例外名稱; 冒號後面為該例外的描述
# 當例外產生時,如果沒有處理,結果就會是程式被中斷執行
```
#### 加上是否為數字的判斷
```python=
# 練習: 請幫猜數字遊戲加上輸入的資料是否為數的的判斷
guess_count = 0 # 紀錄猜了幾次
while True:
player = input('請猜一個四位數的數字,數字不可重複:')
guess_count += 1 # 次數加一
# 檢查輸入是否為數字
try:
int(player) # 嘗試轉型成int
except ValueError:
print('只能輸入整數數字')
continue
except Exception:
print('輸入有問題, 請重新輸入')
continue
# 檢查是否為四個數字
if len(player) != 4:
print('數字只能四個,請重新輸入')
continue
# 檢查是否為四個不重複的數字
if len(set(player)) < 4:
print('數字不可重覆, 請重新輸入')
continue
```
## 類別與物件
```python=
# 類別與物件
# 類別與函式一樣,定義好之後是不會被執行的
# 類別要執行之前,須要先產生物件才能被執行
# 類別內的函式(function)通常會改叫: 方法(method)
# 類別內的變數(variable)通常會改叫: 屬性(attribute)
class Car:
def set_name(self, name): # 類別內的函式第一個參數永遠都是self
self.name = name # self代表的是物件本身
def show_name(self): # 物件裡面的資料是物件內所有方法都可以共同使用的
print(self.name)
def add_gas(self, gas):
self.gas = gas
def show_color(self):
print(f'車子是: {self.color}的')
c = Car() # 建立Car物件
c.set_name('BMW')
c.show_name()
c.color = '紅色' # 將紅色存到color屬性內
c.show_color()
```
#### 類別的預設方法
```python=
class MyItem:
def __init__(self, name, age, tall): # 建構式, 物件被建立時自動被呼叫, 不必自己呼叫, 通常用來初始化物件用
self.name = name
self.age = age
self.tall = tall
print('我被呼叫了')
def show_info(self):
print(f'我叫: {self.name}, 今年{self.age}, 身高{self.tall}公分')
def __str__(self): # 此方法在物件被當字串使用時會自動呼叫
return f'我叫: {self.name}, 今年{self.age}, 身高{self.tall}公分'
m = MyItem('Aaron', 18, 180) # 建立物件, 是個獨立的個體
n = MyItem('Andy', 20, 200) # 建立物件, 與m物件沒有關係
# n.name = 'Andy'
# n.age = 20
# n.tall = 200
m.show_info()
n.show_info()
print(m)
print(n)
```
## 模組
#### my_module.py
```python=
def hello():
print('hello')
class Hello:
def show(self):
print('Show hello')
hello_val = '你好'
```
#### main.py
```python=
# 模組
import my_module
my_module.hello()
m = my_module.Hello()
m.show()
print(my_module.hello_val)
```
#### 引入模組的其他方式
```python=
import my_module as m # 在這個檔案內可以用m來呼叫my_module模組
m.hello()
print(m.hello_val)
```
```python=
# from my_module import hello # 引入模組裡面指定的函式或變數或類別
# from my_module import hello_val
from my_module import * # 將my_module裡面全部的功能都引入進來使用
hello()
print(hello_val)
h = Hello()
h.show()
```