# python 基礎
###### tags: `backend`
詳細教程: https://www.w3schools.com/python/default.asp
Python 是物件導向的高階程式語言。
容易理解與學習且方便使用,可以達到各種難度的應用,也能在大多數的系統中運行。
相較於C++或Java,Python能用較少的程式碼表達。
Python 提供許多 Library(函式庫)讓使用者下載,所以具有龐大且多元的函式庫,可以支援大部份的應用。
另外 Python 擁有 standard library,同時 Python 社群提供了Third-Party模組,
使得Python 發展迅速及使用廣泛,相關資源也相當豐富。
### Python 特點:
* 高階&直譯式程式語言
* 容易撰寫
* 功能強大
* 跨平台,可在多個平台上執行
* 豐富且多元的套件
* 容易擴充,Python具有非常多的第三方程式庫
### Python應用
1. 資料蒐集、資料處理,資料分析視覺化
2. Web開發應用
3. 網絡爬蟲
4. 人工智慧應用(機器學習、深度學習)
5. 資料庫支援
6. 圖形處理
## 01 Python 變數與資料型別
### 變數
python變數不須宣告就可以使用,能自動辨別type。
Python 程式語言中的 `=` 給定值,`==` 相等的值。
```python
#Python宣告
a = "123"
b = '123'
c = 1
d = True
```
```python
# 打印資料型別
print(type(a))
print(type(b))
print(type(c))
print(type(d))
```
### 變數命名規則:
* 只能包含英文、數字和底線
* 變數名稱不能有空格,通常用底線替換 `ex : number_id`
* 不能是保留字 `ex : int` 、`ex : float`
* 英文大小寫不同的就可以為不同變數名稱
### 資料型別
Python資料型別有以下幾種
* Text Type: `str`
* Numeric Types: `int`, `float`, `complex`
* Sequence Types: `list`, `tuple`, `range`
* Mapping Type: `dict`
* Set Types: `set`, `frozenset`
* Boolean Type: `bool`
* Binary Types: `bytes`, `bytearray`, `memoryview`
```python
# int 整數
a = 87
# float 浮點數,小數點
b = 87.878787
# string 字串,文字字元
c = "apple"
# bool 布林,分為 True、False 用於條件判斷
d = True
```
## 02 Python的運算符
### 算術運算子
a=14
b=4
* `a+b` => a、b相加 `a+b = 18`
* `a-b` => a、b相減 `a-b = 10`
* `a*b` => a、b相乘 `a*b = 56`
* `a/b` => a 除以 b `a/b = 3.5`
* `a%b` => a 除以 b的餘數 `a%b = 2`
* `a**b` => a的b次方 `a**b = 38416 (14*14*14*14)`
* `a//b` => a 除以 b,只取整數解 `a//b = 3`
### 賦值運算子
* `a+=b` => `a=a+b`
* `a-=b` => `a=a-b`
* `a*=b` => `a=a*b`
* `a/=b` => `a=a/b`
* `a%=b` => `a=a%b`
* `a**=b` => `a=a**b`
* `a//=b` => `a=a//b`
```python
#算術運算子
#自己輸入兩個數字
num1 = input("輸入第一個數字: ")
num2 = input("輸入第二個數字: ")
num1 = int(num1)
num2 = int(num2)
print(type(num1))
print(type(num2))
print(num1 + num2)
print(num1 - num2)
print(num1 * num2)
print(num1 / num2)
print(num1 % num2)
print(num1 ** num2)
print(num1 // num2)
```
```python
#字串運算
str1 = input("請輸入第一個字串")
str2 = input("請輸入第二個字串")
print(str1 + str2)
print((str1 + str2)*3)
```
### Python 字串格式化以及 f-string 字串格式化
在 Python 裡頭,目前的最新版本 (3.x) 中總共有 3 種不同的方式來達成字串格式化 (String format)。分別是 `%-formatting`、`str.format` 以及 `f-string`。
#### 01. %-formatting
C 語言字串格式化深入我們的生活,Python 自然也不意外的會有這個功能。
```python
# %s = str / %d = decimal 不同變數型態
my_str = 'We have %d apple, %d banana' % (10, 20)
print(my_str)
```
#### 02. str.format
PEP 3101 帶來了 str.format(),讓我們可以用 .format 的方式來格式化字串:
```python
#format 裡放入dictionary
my_str = '{class_name}-{class_seq}'.format(class_name='de', class_seq='01')
print(my_str)
```
#### 03. f-string
PEP 498 帶來了 f-string,它的學名叫作 “Literal String Interpolation”。用法如下:
```python
#建議使用f-string
class_name = 'de'
class_seq = '01'
my_str = f'{class_name}-{class_seq}'
print(my_str)
```
## 03 邏輯運算與判斷式
#### Bitwise運算符
a = 0011 1101
b = 0000 1100
* `&` => 二進位運算的 `and`,`a & b = 0000 1100`
* `|` => 二進位運算的 `or`,`a | b = 0011 1101`
* `^` => 二進位運算的 `xor`,`a ^ b = 0011 0001`
* `~` => 二進位運算的 `not`,`~ a = 1100 0010`
* `<<` => 二進位運算的左移,`a << 2 = 1111 0100`
* `>>` => 二進位運算的右移,`a >> 2 = 0000 1111`
#### 關係運算子
* `==` => 兩值相等為 True
* `!=` => 兩值不相等為 True
* `<>` => 兩值不相等為 True
* `>` => 左值大於右值為 True
* `<` => 左值小於右值為 True
* `>=` => 左值大於或等於右值為 True
* `<=` => 左值小於或等於右值為 True
```python
a = 10
b = 20
print(f'a == b is {a==b}')
print(f'a != b is {a!=b}')
print(f'a > b is {a>b}')
print(f"'hello' == 'hello' is {'hello'=='hello'}")
print(f"'hello' == 'world' is {'hello'=='world'}")
print(f"'a' > 'b' is {'a'>'b'}")
print(f"'b' > 'a' is {'b'>'a'}")
```
#### 邏輯運算子
* `and`: 兩者都成立才為True
* `or`: 其中一個成立就為True
* `not`: 反轉操作,如果其中一個條件成立,反向後回傳為False
```python
# a 和 b 兩者皆大於0才為True,才符合if條件
if ( a and b ):
print("Yes,a 和 b 兩者皆大於0才為True,才符合if條件")
else:
print("No")
# a 和 b 其中之一大於0就為True,就符合if條件
if ( a or b ):
print("Yes,a 和 b 其中之一大於0就為True,就符合if條件")
else:
print("No")
# a 和 b 其中之一大於0就為True,但加上反向not之後則為False
if not( a or b ):
print("Yes")
else:
print("No")
```
#### 判斷式
條件判斷在程式中很重要,要先判斷條件是否成立,才能決定要做什麼事情。
條件判斷經常使用,所使用的就是if指令。
```
if(條件):
執行動作描述句...
elif(條件):
執行動作描述句...
else: #不需要寫條件,當不符合上面的條件,其餘所有狀況都會走這裡。
執行動作描述句...
```
## 04 複雜的資料型別
Python有一些容器類的資料型別(Container type) - list, set, dict, tuple
### List串列
List 串列,可儲存序列資料(可儲不同型別的資料),相較於其他程式語言的陣列更為強大。
python: List用中括號`[]`表示,不同的值用逗號`,`分隔。
範例 :
```python
animals = ['bear', 'cat', 'dog', 'elephant']
numbers = [1, 2, 3, 4, 5]
```
印出List內容操作方式
```python
print (animals) # 輸出完整的list
print (animals[0]) # 輸出list索引值0的位置 => 第一個元素
print(animals[-3]) # 輸出list索引值-3的位置 => 倒數第三個元素
print (animals[1:3]) # 輸出第二到第三個元素
print (animals[1:]) # 輸出第二到最後一個元素
print (animals[:3]) # 輸出第一到第三個元素
```
#### List 修改內容
* `append()` => 從List尾端新增一個元素進去
* `insert()` => 在List的任何位置增加元素
* `del` => 將List該位置的值刪除
* `pop()` => 將List尾端的元素刪除
* `remove()` => 將List中某個數值刪除
```python
animals.append("fox")
animals.insert(1, "bird")
print (animals)
```
原本:`['bear', 'cat', 'dog', 'elephant']`
append:`['bear', 'cat', 'dog', 'elephant', 'fox']`
insert:`['bear', 'bird', 'cat', 'dog', 'elephant', 'fox']`
```python
animals = ['bear', 'bird', 'cat', 'dog', 'elephant', 'fox']
print (animals)
del animals[2] #刪除第三個元素"cat"
print(animals)
animals.pop() #刪除最尾巴的"fox"
print(animals)
animals.remove("dog") #刪除"dog"
print(animals)
```
#### List 函數介紹
* reverse():反轉List的順序
* sort():List排序
* index():某值在List第一次出現的索引位置
* count():某值在List出現的次數
```python
animals = ['bear', 'cat', 'dog', 'elephant', 'cat']
print(animals.index('cat')) # 某值在List第一次出現的索引位置
print(animals.count('cat')) # 某值在List出現的次數
animals.reverse() # 反轉List的順序
print(animals)
animals.sort() # List排序
print(animals)
```
### Dict 字典
key-value的形式
dict 字典,和 list 串列很像但不會使用 0,1,…等的索引index來定位,需要宣告`key鍵值`來對應`儲存的值`。
```python
fruits = {"apple": 10, "banana": 7, "orange": 8}
print(fruits["banana"])
```
#### keys、values、items
* `keys()` => 取得所有key組合,資料型態為dict_keys
* `values()` => 取得所有value組合,資料型態為dict_values
* `items()` => 取得所有 (key,value) 組合,資料型態為dict_items
```python
fruits = {"apple":10, "banana":7, "orange":8}
print(fruits.keys()) #keys()
print(fruits.values()) #values()
print(fruits.items()) #items()
```
### Tuple 元組
類似於 list 串列,但tuple 給定元素後**不能改變**
不同地方在於:list使用`[ ]`,tuple使用`( )`
```python
animals = ('bear', 'cat', 'dog', 'elephant', 'cat')
print(animals)
print(animals[0])
```
用法和List 很像,但是當你試圖想改變 tuple 裡的元素,Python會跟你說tuple的item不能被給值
### Set 集合
set 的內容元素都必須是獨一無二的
```python
fruits_set = {"apple", "banana", "cherry"}
print(fruits_set)
```
## 05 迴圈
### For 迴圈
執行相同的動作,可以藉著for迴圈達到目的,通常與collection物件(如dict,list, tuple, set等等)一起使用,在給定的某個條件下,可以重複做某些動作。
以下為For迴圈的語法:
設定一個變數在某個range下重複執行:
```
for 變數 in range(star, end, 遞增值)
```
```python
for i in range(0, 10):
print(i)
```
範例:從0加到9
```python
sum = 0
for i in range(0,10):
sum += i
print(sum)
```
**list** 通常與 for 搭配使用
範例:
```python
animals = ['bear', 'bird', 'cat', 'dog', 'elephant', 'fox']
for animal in animals:
print(animal)
```
**dict** 也可以和 for 搭配使用
* 拿出dict裡的`keys`
```python
fruits = {"apple": 10, "banana": 7, "orange": 8}
for x in fruits:
print(x)
```
* 取出`key`對應的`值value`
```python
fruits = {"apple": 10, "banana": 7, "orange": 8}
for x in fruits:
print(fruits[x])
```
* 取出 `key,value` 組合
```python
fruits = {"apple": 10, "banana": 7, "orange": 8}
for x in fruits:
print(x, fruits[x])
```
### While 迴圈
當while內的條件成立就會執行內部程式碼,當程式需要不斷重覆某些運算,一直到出現符合設置的條件狀況才停止。
while用法:
```
while 條件為真:
重複執行
```
```python
# 跑出 0-9
x = 0
while (x < 10):
print(x)
x += 1
```
```python
# 加總0~9
sum = 0
i = 1
while i < 10:
sum += i
i += 1
print(sum)
```
#### continue
在迴圈通常要把“內部動作”執行完一遍之後,才會重新比對迴圈條件是否成立。但在某些時候我們希望他不要執行“內部動作”,跳過這次回圈,直接重新比對迴圈條件是否成立,這時候就是使用`continue`。
通常搭配 if...當某個條件成立,就跳過“執行內容”直接進入下一個迴圈。
```
for 或 while ( ..... ):
......
if (條件式)
continue
......
```
```python
# 範例: 0~9加總,但排除5
x = 0
sum = 0
while x < 10:
if (x==5):
x += 1
continue
sum += x
x += 1
print(sum)
```
#### break
break 用來停止 while 執行,while 為True 表示迴圈永遠成立,會一直執行。如果在迴圈內部加上 if 判斷條件和 break,就能讓迴圈條件成立的情況下結束執行。
```
for 或 while ( ..... ):
......
if (條件式)
break
......
```
```python
# 範例: 0~9加總,讓while 為True 表示迴圈永遠成立,當x=10則停止。
x = 0
sum = 0
while True:
sum += x
x += 1
if(x==10):
break
print(sum)
```
## 06 字串處理
字串運用 - 單引號、雙引號括起來的都是字串。
字串的常見用法:
### 字串切割 - split()
當我們輸入的文字檔或者接收到的資料,可以利用`split()`切割字串,
轉換成 list 方便後續分析處理。
```
str.split(str=''). #' ' 填入要分割的符號
```
```python
str1 = 'bear, cat, dog, elephant'
arr = str1.split(', ')
print(arr)
```
### 取得特定範圍的字串
string 和 list 一樣都可以取特定部分的內容
```python
str1 = 'hello world'
print (str1) # 輸出完整的str
print (str1[0]) # 輸出str1索引值0的位置 => 第一個字元
print(str1[-3]) # 輸出str1索引值-3的位置 => 倒數第三個字元
print (str1[1:8]) # 輸出第二到第八個字元
print (str1[1:]) # 輸出第二到最後一個字元
print (str1[:7]) # 輸出第一到第七個字元
```
### 大小寫轉換
```python
str1 = 'hello world!'
print(str1.upper()) #全部字元轉成大寫
print(str1.lower()) #全部字元轉成小寫
print(str1.swapcase()) #將大小寫顛倒
print(str1.title()) #每個單字首字大寫
print(str1.capitalize()) #第一個字母大寫
```
### 計算字串長度
```python
str1 = 'hello world!'
str2 = 'python!'
print(len(str1),len(str2))
```
### 替換字串
```
str.replace(old, new[, max])
```
參數
* old -> 要更換的字串。
* new -> 新的字串。
* max -> 最多換掉幾次。
```python
str1 = "Today is great for learning python! That is good! This is example"
print(str1.replace("is", "was"))
print(str1.replace("is", "was", 2))
```
### 查找字串
```
str.find(str, beg=0 end=len(string))
```
參數
* str -> 要找的字串。
* beg -> 開始找的位置。
* end -> 結束的位置。
回傳
* 如果有找到就回傳位置,沒有找到則回傳-1
```python
str1 = 'hello world!'
str2 = 'hello'
print(str1.find(str2))
```
### 字串串連
```
str.join(sequence)
```
```python
str1 = ' & '
tup = ('a', 'b', 'c')
print(str1.join(tup))
```
## 07 如何處理 JSON
很多資料的傳輸格式都是使用json, 所以對於json資料處理就很重要。
JSON(JavaScript Object Notation)輕量級的資料交換語言,容易閱讀的文字為主,用來傳輸由屬性值或者序列性的值組成的資料物件。
### JSON格式:
* 陣列(array)用中括號 `[ ]`
* 物件(object)用大括號 `{ }`, 用key-value的方式儲存
```json
{
"id": 123,
"Name": "wsrsw",
"Email": "wsrsw@example.com",
"contents": [
{
"subject":"Math",
"score":80
},
{
"subject":"English",
"score":90
}
]
}
```
### JSON 模組
json是現有REST API的主流形式。json的編碼和解碼在python 中可以透過`json`套件完成。
json與python資料類型轉換關係表:
Python|JSON
:----:|:--:
dict|object
list, tuple|array
str, unicode|string
int, long, float|number
True|true
False|false
None|null
### Python物件與JSON類型轉換
#### JSON字串轉Python dict
python json字串轉成python物件
需要使用json模塊的`loads()`
```python
import json
str1 = '{"id": 123, "Name": "simon", "Email": "simon@wistron.com"}'
j = json.loads(str1)
print(j)
print(type(j))
```
### Python dict轉JSON字串
python物件轉json字串
需要使用json模塊的`dumps()`
```python
import json
j = {'id': 123, 'Name': 'simon', 'Email': 'simon@wistron.com'}
str1 = json.dumps(j)
print(str1)
print(type(str1))
```
### Python dict包含list轉JSON字串
可以使用`indent` => 可以使得數據存儲的格式容易解讀。
```python
import json
# dict
python_dict = {"id": [1, 2, 3], "name": ["Tim", "Bob", "Lucy"]}
print(python_dict)
# convert to json string
j = json.dumps(python_dict, indent = 4)
print(j, type(j))
```
## 08 檔案 I/O
### 讀取檔案
在python可以處理文字檔中的資訊,可以一次讀取全部的內容,也可以一行一行的讀取。
Python內建函式`open()`可以開啟指定檔案,可以讀取、寫入和修改檔案內容。
#### open(): 開啟檔案
```
open(filename[,mode])
```
參數:
* filename 要讀寫的檔案名稱 (字串型態、不可省略)。
* mode 開啟檔案的模式 (字串型態、可以省略,預設為讀取r)。
通常都是用r、w、a來控制。
檔案讀寫模式如下:
字元|說明
:---|:-----------------------------------------------------------
r |只讀取檔案(唯讀)。檔案必須存在。
r+ |讀取寫入檔案(讀寫)。不會新建檔案,檔案必須存在,寫入會覆蓋原本內容。
w |新建寫入檔案(只寫)。文件內容清零。
w+ |新建讀取寫入檔案(讀寫)。文件內容清零。
a |寫入檔案(只寫)。新增在檔案後面,不會覆蓋原本的。
a+ |允許新增與讀取(讀寫)。新增在檔案後面,不會覆蓋原本的
#### close(): 關閉檔案,關閉後就不能進行讀寫動作
```python
# 寫入檔案
# 使用w+
f = open("test.txt", "w+")
f.write( "123\n")
f.close()
# 使用r+
f = open("test.txt", "r+")
f.write( "456\n")
f.close()
# 使用a+
f = open("test.txt", "a+")
f.write( "789\n")
f.close()
```
這時候就會出現一個txt檔案,來看一下內容吧!
```text
456
789
```
所以可以知道 r+ 是會覆蓋檔案,a+ 則是附加在檔案後面!
再來試試輸入一次試試看r+如何覆蓋檔案。
```python
# 使用w+
f = open("test.txt", "w+")
f.write( "try123\n")
f.close()
# 使用r+
f = open("test.txt", "r+")
f.write( "456\n")
f.close()
# 使用a+
f = open("test.txt", "a+")
f.write( "789\n")
f.close()
```
結果:
```
456
23
789
```
r+寫入了456\n 一共是4個元素(\n為換行),並且加在檔案最前面,
因此他蓋掉了w+ 的前4個元素,所以就只剩下23。
### 檔案處理
來創建個簡單的txt檔案吧!
```
檔名= hello.txt
Hello
World
123
456
789
```
把檔案讀取進來後,接著就是將檔案內容放進變數裡。
這裡介詔三種方法:
* read()
* readline()
* readlines()
#### read([size]) 方法:
size 可以指定要讀取多少字元,沒指定就是讀取全部。
```python
f = open('hello.txt', 'r')
lines = f.read() # 沒指定size
print(lines)
print(type(lines))
f.close()
```
#### readline() 方法:
每次讀一行 => 讀取時佔用記憶體小,比較適合大檔案。
```python
f = open('hello.txt', 'r')
line = f.readline().replace('\n','') #去掉換行
while line:
print(line)
line = f.readline().replace('\n','') #去掉換行
f.close()
```
#### readlines() 方法:
讀取整個檔案內容,儲存在list串列中,一行為一個元素,讀取大檔案會比較佔記憶體。
若使用`with`則不須使用`f.close()`。
```python
with open('hello.txt', 'r') as f:
lines = f.readlines()
print(lines)
```
## 09 函式 Function
一旦程式功能變多,相同的功能的程式碼會重複出現,導致程式碼太長、太醜、太難修改,所以需要函式來簡化 - 相同事件只要寫一次就好。
函式(function):可以設置參數,也可以數值傳給其他函式,以及return value。
語法:`def functionName()`: 用`:`縮排來表示function區塊。
* 定義函式-我們需要用到`def`關鍵字來告知python我們要定義一個函式
```python
def try_function(): # 定義try_function()函式
print("hello world") # 函式的工作是印出hello world
return(1+1) # 函式回傳的值
x = try_function() # 呼叫try_function()函式,函式回傳的值放進x變數中
print(x)
```
* 把參數帶入函式內 - 在已經定義的函式括號內放入參數。
```python
def try_function(name): # 定義try_function()函式,接收name這個參數
print("Hello " + name) # 函式的工作是印出Hello 加上參數name的值
try_function("data engineer") # 呼叫try_function()函式,函式帶入'data engineer'參數
```
### 遞迴
在解決問題時有時需要回到上一個計算或者需要應用到上一個解法的答案,此時就是利用遞迴的概念來撰寫一個函式。
* 特點:
* 將大問題拆解成重複性的小問題
* 自己呼叫自己、設置終止目標
* 範例:階乘、費氏數列、最大公因數、最小公倍數...
階乘 Factorial
`n! = 1 x 2 x ... x (n-1) x n`
`n! = n x (n-1)!`
`n! = n x (n-1) x (n-2) x (n-3) ... x 1`
3! = 3x2x1
Factorial(3)
= 3 * Factorial(2)
= 3 * 2 * Factorial(1)
= 3 * 2 * 1
```python
def factorial(n):
if n == 1:
return 1
else:
return n * factorial(n-1)
num = int(input('請輸入數字: '))
answer = factorial(num)
print(str(num) + '! = ' + str(answer))
```
## 10 類別 Class
物件導向當中的類別是抽象描述那些有共同性質的物件,大家可以一起使用,不需重複輸寫,方便且容易修改。內容描述了該類別物件共同的性質,及實現共同行為的方法。
例如對學生資料大家都是相同的:
類別名稱: Student
資料:班級、姓名、學號、手機
分數:國文、英文、數學、自然
* 語法:
* 使用class來完成類別的結構
* 定義類別的語法 => class 類別名稱:
* 宣告物件的方法 => 物件名稱 = 類別建構子名稱
```
class 類別名稱:
#類別建構式
def __init__(self, 其他參數...):
.
.
def 自訂方法(self, 其他參數...):
.
.
```
* 建構子:
建構子語法如下:
`def __init__(self, 其他參數):`
就算是在建構子裡面`self`也是必須傳入的參數!這個方法的開頭和結尾都有兩個**底線**。
範例:
Student開啟一個類別,代表所有學生可以取用這個類別的設定,避免重複的函式。
```python
class Student():
def __init__(self, name, age):
self.name = name
self.age = age
a = Student("Simon", 11) #建立一個名叫Simon的Student實體(物件)
print(a.name)
print(a.age)
```
範例中加了一個name屬性,在創class時,都必須要給這個屬性一個參數
才能成功創造實體。
* 取用Class自己的屬性
使用類別自己的變數、函數都須要加上`self.`變數名稱才能使用
```python
class Student():
def __init__(self, name, num):
self.name = name
self.num = num
def avg(self, chinese, english, math):
avg = chinese + english + math
avg /= 3
return avg
s = Student("Simon",22) #變數s 呼叫Student() class
print("學生姓名:" + s.name)
print("學生座號:" + str(s.num))
avg = s.avg(90, 80, 70) #直接使用s.avg 呼叫 Student()裡面的avg function
print("分數平均:" + str(avg))
```