# Python Basic fundamental
###### tags: `python`
---
>
>* **本文內容為“Tibame快速闖關Python語法世界,程式實作不頭痛”為主,版權為issac所有,本文僅做筆記用途,非商業用途**
>
>* **本篇圖片部分出自“Tibame快速闖關Python語法世界,程式實作不頭痛”課程內容講義**
>
---
# :memo: Introduction
## 1. Python特色
- 可讀性高
- 跨平台
- 豐富第三方套件
- 直譯式語言
- 腳本語言
- 膠水語言
## 2. python生態系

# :memo: Principle of Operation
## 1. Python keyword

## 2. Python Identifier
Identifier命名可區分不同名稱:
- 變數(Variable)
- 函數(Function)
- 類別(Class)
Identifier命名規則
- 由 A-Z, a-z, 0-9, _所組成
- 第一字元不可為0-9
- 大小寫有區別
- 不要使用keyword命名
Identifier命名偵測是否有效
```python=
print("abc".isidentifier()) #True
print("99a".isidentifier()) #Flase
```
Identifier命名格式
- snake_case(ex: my_cat_name, my_cat_age)
- lowerCamelCase(ex: myCatName, myCatAge)
- UpperCamelCase(ex: MyCatName, MyCatAge)
- CAPITZLIZE(ex:PI,HOSTNAME)
## 3. Python Literals
**1. Literals為Python內建給予變數與常數的原始資料**
String literals : "halo" , '12345'
Int literals : 0,1,2,-1,-2
Long literals : 89675L
Float literals : 3.14
Complex literals : 12j
Boolean literals : True or False
Special literals : None
Unicode literals : u"hello"
List literals : [], [5,6,7]
Tuple literals : (), (9,),(8,9,0)
Dict literals : {}, {'x':1}
Set literals : {8,9,10}
**2. Numeric Literals (進位)**
EX:數字10,11
Decimal (十進位): 10, 11
Binary (二進位): 0b1010, 0B1011
Octal (八進位): 0o12, 0O13
Hexadecimal (十六進位): 0xa, 0XB
**3. 逃脫字元**

## 4. Python Variable
**定義:用來儲存數值而被保留之記憶體**

**Object (物件)**
變數從memory找到對應之物件提取其內容

其中包含id、type、value
- identity(id):回傳此物件在memory中的位置
- type:物件之型別
- value:物件內之值

**動態類型**
Python為動態類型語言,可自動偵測變數之型別
C/Java為靜態類型語言,需要先指定變數型別
**命名規則**
- 只能透過英文大小寫(A-Z,a-z), 數字(0-9), 底線(_)
- 不能用數字作為開頭
- 區分大小寫
- 底線(_)開頭
## 5. Python Operator
- Arithmetic Operator: ==+, -, *, /, %, **, //==
:::info
:bulb:Hint: %表示餘數,//表示商
:::
- Comparison Operator: ==\==, !=, >, <, >=, <\===
- Assignment Operator

- Logical Operator: ==and, or, not==
- Membership Operator: ==in, not in==

- Identity Operator: ==is, is not==

- Bitwise Operator: ==&, |, ^, <<, >>==
&: AND(Both True=>True, Other=>False)
|: OR(Both False=>False, Other=>True)
^: XOR(True False=>True, Other=>False)
<<, >>:Shift Bit


- 運算優先順序

# :memo: Data Types
## 1. Numeric Type (int, float, complex)
| int | float |complex |
| --------|----------|----------|
| 5 | 0.0 | 5+3j |
| 22 | 22.5 | 5.j |
| -3 | -3.89 | -3.89j |
| 0b1010 | -3. | .3j |
| -0b1011 | 18.3e+9 | 18.3e+9j |
| 0x220 | -18.3e+9 | 18.3e-9j |
## 2. Boolean Type (bool)
Boolen only **True** or **False**

## 3. Sequence Type (str, list, tuple)
### **string**
Imutable
#### 1. 常見string函數
```python=
s = "Surprise"
s2 = "MotherFucker"
print(s[0]) #S
print(s[4:]) #rise
print(s[0::2]) #Srrs
print(s+s2) #SurpriseMotherFucker
print(s*2) #SurpriseSurprise
print(len(s)) #8
print(min(s)) #S
print(max(s)) #u
print("S" not in s) #False
print("M" in s2) #True
```
#### 2. string分割函數
```python=
s3 = "I Love U"
print(s3.split()) #['I', 'Love', 'U']
mails = ["abcn@yahoo.com.tw", "wooddn@hotmail.com", "kkzaa@gmail.com"]
print(mails[0].split("@")[1].split(".")[0]) #先用@分割,再用.分割
#"yahoo"
```
#### 3. string去首尾函數
```python=
str1 = "乂JoJo乂乂"
str2 = " 乂JoJo乂乂 "
print(str1.strip("乂")) #"JoJo"
print(str2.strip()) #"乂JoJo乂乂"
a = "\tabc"
b = "abc\n\r"
print(a.strip()) #"abc"
print(b.strip()) #"abc"
```
#### 5. string 單引號&雙引號應用
```python=
print("I'm Joseph") #雙引號內單引號不用跳脫
print('I\'m Joseph') #單引號內有單引號要跳脫
print('I said "Why"') #單引號內雙引號不用跳脫
print("I said \"Why\"") #雙引號內有雙引號要跳脫
```
### **list**
定義1:list為**有序**且**可修改**之元素集合(mutable)
定義2:允許多個重複元素
定義3:允許list內元素為不同type
Example: name_list = ['Joseph', 'Emma', 'Julia', 'Julian']
| list | Joseph | Emma | Julia | Julian |
| ------------------|--------|------|-------|--------|
| Index from head | 0 | 1 | 2 | 3 |
| Index from tail | -4 | -3 | -2 | -1 |
#### 1. 常見字串函數
```python=
name_list = ["Joseph", "Emma", "Julia", "Julian"]
name_list.append("Judy") #['Joseph', 'Emma', 'Julia', 'Julian', 'Judy']
name_list.remove("Judy") #['Joseph', 'Emma', 'Julia', 'Julian']
name_list2 = name_list.copy() #['Joseph', 'Emma', 'Julia', 'Julian']
name_list.index("Emma") #1 (位置1)
name_list.extend(name_list2) #['Joseph', 'Emma', 'Julia', 'Julian', 'Joseph', 'Emma', 'Julia', 'Julian']
name_list.count("Julia") #2 (出現兩次)
name_list2.insert(2, "Judy") #['Joseph', 'Emma', 'Judy', 'Julia', 'Julian']
del name_list2[2] #['Joseph', 'Emma', 'Julia', 'Julian']
name_list2.pop() #['Joseph', 'Emma', 'Julia'] (最尾巴的去除)
print(name_list2.pop()) #Julia, name_list2 = ['Joseph', 'Emma']
name_list.reverse() #['Julian', 'Julia', 'Emma', 'Joseph', 'Julian', 'Julia', 'Emma', 'Joseph']
name_list.sort() #['Emma', 'Emma', 'Joseph', 'Joseph', 'Julia', 'Julia', 'Julian', 'Julian']
#replace不改寫list,此用法會回傳新的字串
list1 = ["Holy", "Shit"]
list1[1].replace("S", "s") #shit
print(list1) #["Holy", "Shit"]
name_list.clear() #[]
```
#### 2.list合併函數
```python=
list1 = ["S", "H", "I", "T"]
print("".join(list1)) #SHIT
print('-'.join(list1)) #S-H-I-T
```
#### 3.list值合併函數
```python=
#list中值加總
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(sum(list1)) #45
#list與list之間合併
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list3 = list1 + list2 #[1, 2, 3, 4, 5, 6]
#list與list之間合併成dict
list_a = ["Joseph", "Emma", "Julia"]
list_b = [1, 2, 3]
dic1 = dict(zip(list_a, list_b)) #{'Joseph': 1, 'Emma': 2, 'Julia': 3}
```
### **tuple**
定義1:tuple為**有序**且**不可修改**之元素集合(immutable)
定義2:“**不**”允許多個重複元素
定義3:允許tuple內元素為不同type
Example: person1 = ("Joseph", 180, 75)
| tuple | Joseph | 180 | 75 |
| ------------------|--------|-----|----|
| Index from head | 0 | 1 | 2 |
| Index from tail | -3 | -2 | -1 |
#### 1. 常見字串函數
```python=
person1 = ("Joseph", 180, 75)
person1 += ("Taipei", ) #利用逗號來使程市判別()內為tuple而非運算用
print(person1) #("Joseph", 180, 75, "Taipei")
print(person1[0]) #Joseph
print(person1[:2]) #Joseph 180
print(len(person1)) #4
#person1[0]與person1[0:1]不同,一個是單一文字,一個是tuple型態
print(person1[0]) #"Joseph"
print(person1[0:1]) #("Joseph",)
print(person1[0:1] + person1[2:]) #("Joseph", 75, 'Taipei')
# tuple刪除? 不用,因為本身是短暫用
# 要用也可,可以繞彎達成
```
#### 2.list合併函數
```python=
t1 = ("S", "H", "I", "T")
print("".join(t1)) #"SHIT"
print('-'.join(t1)) #"S-H-I-T"
```
#### 3.sort()函數
```python=
#Sorted()輸出為list
t1 = ("S", "H", "I", "T")
print(sorted(t1)) #['H', 'I', 'S', 'T']
```
## 4. Hash Type (dict, set)
### **dict**
定義1:dictionary為無序且一堆**key** & **value**之元素集合
定義2:key不可重複
#### 1. 常見字串函數
```python=
person = {"Name":"Joseph", "Height":180, "Handsome":True}
#取值: print(name)
print("Name: ", person["Name"]) #Name: Joseph
#新增語法
person["Weight"] = 75
print(person) #{'Name': 'Joseph', 'Height': 180, 'Handsome': True, 'Weight': 75}
#更新內容
person["Weight"] = 72
print(person) #{'Name': 'Joseph', 'Height': 180, 'Handsome': True, 'Weight': 72}
#數值取出來做運算並且更新
person["Height"] = person["Height"] +3
print(person) #{'Name': 'Joseph', 'Height': 183, 'Handsome': True, 'Weight': 72}
#刪除
del person["Weight"]
print(person) #{'Name': 'Joseph', 'Height': 177, 'Handsome': True}
#len
print(len(person)) #3
```
#### 2. iter()函數
```python=
lis1 = {"A":11, "B":22, "C":33, "D":44, "E":55}
print(id(lis1))
# printing type
print ("The list is of type:" + str(type(lis1)))
# converting list using iter()
lis1 = iter(lis1)
print(id(lis1))
# printing type
print ("The iterator is of type:" + str(type(lis1)))
# using next() to print iterator values
print (next(lis1))
print (next(lis1))
print (next(lis1))
print (next(lis1))
print (next(lis1))
```
### **set**
定義1:set為無序且無索引(index)之元素集合
定義2:不可重複元素
#### 1. 常見字串函數
```python=
name_set = {"周", "林", "黃", "周"}
print(name_set) #{'黃', '周', '林'}
# 會改變set內部指令:add, discard
name_set.add("王") #{'黃', '周', '林', '王'}
name_set.discard("王") #{'黃', '周', '林'}
#聯集:兩個的聯集
name_set = name_set.union({"何", "周"})
print(name_set) #{'周', '何', '黃', '林'}
```
## 5. String formatting
```python=
a = 100
b = 8.9
c = "hello"
d = 1+2j
print("{} {} {}".format(a, b, c) #"100 8.9 hello"
print("{0} {1} {2}".format(a, b, c)) #"100 8.9 hello"
print("{2} {1} {0}".format(a, b, c)) #"hello 8.9 100"
print("{0}, {0.real}, {0.imag}".format(d)) #(1+2j), 1.0, 2.0
print("x, y = {x}, {y}".format(x="3", y="4")) #x, y = 3, 4
#dict type
coord = {"w": "6", "h": "8"}
print("w, h = {w}, {h}".format(**coord)) #w, h = 6, 8
#tuple type
coord2 = (8, 9)
print("X: {0[0]}; Y: {0[1]}".format(coord2)) #X: 8; Y: 9
#調整位數
#hint: d=integer f=float s=string
print('{0:10d} {1:10f} {2:10s}'.format(a, b, c)) #設10個位數
print('{0:>10d} {1:>10f} {2:>10s}'.format(a, b, c)) #靠右
print('{0:<10d} {1:<10f} {2:<10s}'.format(a, b, c)) #靠左
print('{0:^10d} {1:^10f} {2:^10s}'.format(a, b, c)) #靠中間
#' 100 8.900000 hello '
#' 100 8.900000 hello'
#'100 8.900000 hello '
#' 100 8.900000 hello '
#進位
#hint: int:十進位 bin:二進位 oct:八進位 hex:十六進位
print('int: {0:d}; bin: {0:b}; oct: {0:o}; hex: {0:x}'.format(99))
#'int: 99; bin: 1100011; oct: 143; hex: 63'
print('int: {0:#d}; bin: {0:#b}; oct: {0:#o}; hex: {0:#x}'.format(99))
#'int: 99; bin: 0b1100011; oct: 0o143; hex: 0x63'
print(':,'.format(1234567890))
#'1,234,567,890'
#小數點
e = 33
f = 19
print('percentage = {:.2%}'.format(b/a)) #小數點兩位
#'percentage = 57.58%'
#時間格式
import datetime
date1 = datetime.datetime(2020, 1, 1, 12, 34, 56)
print('{:%Y-%m-%d %H:%M:%S}'.format(date1))
#'2020-1-1 12:34:56'
```
[f-string](https://www.twblogs.net/a/5b822eca2b717737e032da80)
Better and faster than format
```python=
a = 100
b = 8.9
c = 'hello'
d = 1+2j
print(f"{a} {b} {c}") #"100 8.9 hello"
#dict type
coord = {"w": "6", "h": "8"}
print(f"w, h = {coord['w']}, {coord['h']}") #w, h = 6, 8
#tuple type
coord2 = (8, 9)
print(f"X: {coord2[0]}; Y: {coord2[1]}") #X: 8; Y: 9
#調整位數
#hint: d=integer f=float s=string
print(f"{a:10d} {b:10f} {c:10s}") #設10個位數
print(f"{a:>10d} {b:>10f} {c:>10s}") #靠右
print(f"{a:<10d} {b:<10f} {c:<10s}") #靠左
print(f"{a:^10d} {b:^10f} {c:^10s}") #靠中間
#' 100 8.900000 hello '
#' 100 8.900000 hello'
#'100 8.900000 hello '
#' 100 8.900000 hello '
#進位
#hint: int:十進位 bin:二進位 oct:八進位 hex:十六進位
print(f"int: {99:d}; bin: {99:b}; oct: {99:o}; hex: {99:x}")
#'int: 99; bin: 1100011; oct: 143; hex: 63'
print(f"int: {99:#d}; bin: {99:#b}; oct: {99:#o}; hex: {99:#x}")
#'int: 99; bin: 0b1100011; oct: 0o143; hex: 0x63'
print(f"{1234567890:,}")
#'1,234,567,890'
#小數點
e = 33
f = 19
print(f"percentage = {f/e:.2%}") #小數點兩位
#'percentage = 57.58%'
#時間格式
from datetime import datetime as dt
date1 = dt(2020, 1, 1, 12, 34, 56)
print(f"{date1:%Y-%m-%d %H:%M:%S}")
#'2020-1-1 12:34:56'
```
# :memo: Flow
## 1. 條件式 if/else/elif
定義1:True/False條件敘述,若條件式為True則執行縮排內程式區塊
定義2:執行順序為if==>elif==>elif...==>else
```python=
import random
answer = random.randint(1, 5)
guess = int(input("Guess: "))
if guess > answer:
print('{} is bigger than answer'.format(guess))
elif guess < answer:
print('{} is smaller than answer'.format(guess))
else:
print('bingo! is ', answer)
```
### 巢狀式流程控制
```python=
import random
answer = random.randint(1, 5)
guess = int(input("Guess: "))
if guess >= 1 and guess <=5:
if guess > answer:
print('{} is bigger than answer'.format(guess))
elif guess < answer:
print('{} is smaller than answer'.format(guess))
else:
print('bingo! is ', answer)
else:
print("Guess is not in range")
```
## 2. 迴圈 while/for
### **while**
定義:在條件式為True時,可重複執行某一段程式區塊
```python=
answer = 3
guess = 0
while guess != answer:
guess = int(input('please make guess during 1~6.: '))
if guess > answer:
print('bigger than answer')
continue #直接跳去while那一行
elif guess < answer:
print('smaller than answer')
else:
print('bingo')
break #中斷此while迴圈
print('Still in while loop.\n')
```
### **for**
定義:用來迭代序列化資料,ex: list, tuple, dictionary
```python=
for i in 'Joseph':
print(f'{i}', end='') #f'{}'方便做帶入
#Joseph
```
```python=
Name_list = ['Joseph', 'Emma', 'Julian']
for i in Name_list:
print(f'Name: {i}')
# Name: Joseph
# Name: Emma
# Name: Julian
for i in range(len(Name_list)):
print(i)
print(my_list[i])
# 0 Joseph
# 1 Emma
# 2 Julian
for index, i in enumerate(Name_list):
print(index,i)
# 0 Joseph
# 1 Emma
# 2 Julian
pos = [i for i,x in enumerate(Name_list) if x == "Joseph"]
#[0]
```
```python=
for i in range(5):
print(i, end='') #01234
print('')
for i in range(1, 5):
print(i , end='') #1234
print('\n', end='')
for i in range(1, 10, 2):
print(i, end='') #13579
print('\n', end='')
for i in range(5, 0, -1):
print(i, end='') #54321
```
```python=
my_dict = {'Joseph':50, 'Emma':80, 'Judy':20}
for i in my_dict:
print(i, my_dict[i])
# Joseph 50
# Emma 80
# Judy 20
for i in my_dict.values():
print(i)
# 50
# 80
# 20
```
巢狀迴圈
```python=
n=5
for i in range(n):
for j in range(i):
print ('* ', end="")
print('')
for i in range(n,0,-1):
for j in range(i):
print('* ', end="")
print('')
# *
# * *
# * * *
# * * * *
# * * * * *
# * * * *
# * * *
# * *
# *
```
# :memo: Function
## 自訂函數
定義:A-Z, a-z, *_*,0-9,第一個不能為數字
定義:可設計成輸入參數(parameters)與回傳值(return)
```python=
#可以設預設值
def score(name, grade, class1='Sunny'):
print(name + "'s math grade is: %s" %grade)
print(r'class is', class1)
score('Joseph', 98)
# Joseph's math grade is: 98
# class is Sunny
#可以將參數變“動參數”增加多個參數輸入
def namelist(*names):
for name in names:
print(name)
return names #--> tuple
namelist('Joseph', 'Emma', 'Julian')
# Joseph
# Emma
# Julian
#可以將參數變“動參數”接收字典
def feature(**keyvalue):
print('FEATURE:', keyvalue)
return keyvalue #-->dict
feature(Name='Joseph', Height=180, Handsome=True)
# FEATURE: {'Name': 'Joseph', 'Height': 180, 'Handsome': True}
#回傳值功能
def Returnfuc():
a = 'apple'
b = 'banana'
c = 'cat'
return a, b, c
print(Returnfuc())
# ('apple', 'banana', 'cat') type==>tuple
```
## 內建函數

### 常用函數
```python=
abs(-1) #1
round(3.4) #3
pow(3,2) #9
divmod(3,2) #(2,1)
str(10) #10
bin(10) #0b1010
oct(10) #0o12
hex(10) #0xa
list1 = [1,2,3,4,5]
sum(list1) #15
min(list1) #1
max(list1) #5
txt1='100'
a = int(txt1)
print(f'a = {a}, {type(a)}') #a = 100, <class 'int'>
txt2='100.87'
b = float(txt2)
print(f'b = {b}, {type(b)}') # b= 100.87, <class 'float'>
```
## 全域變數
定義:任何區塊的程式碼可存取之變數
```python=
def function2():
global a #將變數a變為全域變數,函數跳出時變數a才不會消失
a += 1 #變數a變成1000
print(a)
a = 999
function2()
#1000
```
## 區域變數
定義:只能在程式區塊可存取之變數
```python=
def sumofbitch(a, b):
c = a + b #變數a, b, c只存取於此程式區塊
print(a)
return c
print(sumofbitch(1,2))
#1 先運算sumofbitch(1,2)
#3 後print
```
## lambda函數
定義:使用一行就能完成函數定義
```python=
#before
def double(a):
return a*2
double(5) #10
#after
x = lambda a:a*2
x(5) #10
```
結合filter()可選則符合條件之元素
```python=
#filter(function, iterable)
list1 = [1,2,3,4,5,6,7,8,9]
odd_list = list(filter(lambda x:(x%2==1),list1))
print(odd_list)
# [1, 3, 5, 7, 9]
```
結合map()可選所有元素一起轉換
```python=
#map(function, iterable)
list1 = [1,2,3,4,5,6,7,8,9]
odd_list = list(map(lambda x:x**2,list1))
print(odd_list)
# [1, 4, 9, 16, 25, 36, 49, 64, 81]
```
結合reduce()可選多個元素做合併
```python=
#reduce(function, iterable)
from functools import reduce
list1 = [1,2,3,4,5]
odd_list = reduce(lambda x, y:x+y,list1)
print(odd_list) #((((1+2)+3)+4)+5)
# 15
```
## 遞迴函數
定義:自己呼叫自己
```python=
def factorial(n):
if n==0 or n==1:
return 1
else:
return n*factorial(n-1)
print(factorial(4)) #24
```
### 動態規劃
因為避免遞迴浪費太多記憶體,可先將部分函數存起來,要用到可直接取得
以費氏定理來舉例:
|F(0)|F(1)|F(2)|F(3)|F(4)|F(5)|F(6)|F(7)|F(8)|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|0 |1 |1 |2 |3 |5 |8 |13 |21 |
```python=
#before
def F(n):
if n==0 or n==1:
return n
else:
return F(n-1)+F(n-2)
print(F(8)) #21
#after
def fibonacciVal(n):
memo = [None]*(n+1)
memo[0], memo[1] = 0, 1
for i in range(2, n+1):
memo[i] = memo[i-1]+memo[i-2]
return memo[n] #memo[2] = 1, memo[3] = 2,...
print(fibonacciVal(8)) #21
```
# :memo: Class
## 物件導向語言(Object-oritented Programming,OOP)
定義1:所有資料皆是物件
定義2:提高軟體重複使用性、方便擴充性、方便維護性
## 基本語法
定義:第一個字母要大寫
```python=
class Banks():
title = 'Taiwan Bank'
def word(self):
print("Hello!!")
bank1 = Banks()
print(bank1.title)
bank1.word() #有self需要有()
#Taiwan Bank
#Hello!!
```
### 1.\_\_init\_\_函數
class被創建時,\_\_init\_\_會被直接執行
```python=
class Banks():
def __init__(self, uname):
self.name = uname #public==>他人可以查詢得到
self.balance = 0
self.bankname = "Taipei Bank"
def save_money(self, money):
self.balance += money
print("save ", money, "Finish")
def withdraw_money(self, money):
self.balance -= money
print("draw ", money, "Finish")
def get_balance(self):
print(self.name, "Rest: ", self.balance)
bank1 = Banks('Joseph')
bank1.save_money(300) #save 300 Finish
bank1.get_balance() #Joseph Rest: 300
bank1.withdraw_money(300) #draw 300 Finish
bank1.get_balance() #Joseph Rest: 0
```
### 2.實體屬性(Instance Attribute)
定義:各自物件實體屬性各自獨立,修改某一物件屬性時,不會影響另一物件之屬性
```python=
class Banks():
def __init__(self, uname):
self.name = uname #public==>他人可以查詢得到
self.balance = 0
self.bankname = "Taipei Bank"
def save_money(self, money):
self.balance += money
print("save ", money, "Finish")
def withdraw_money(self, money):
self.balance -= money
print("draw ", money, "Finish")
def get_balance(self):
print(self.name, "Rest: ", self.balance)
bank1 = Banks('Joseph')
bank2 = Banks('Emma')
bank1.save_money(300) #save 300 Finish
bank1.get_balance() #Joseph Rest: 300
bank2.save_money(1000) #save 1000 Finish
bank2.get_balance() #Emma Rest: 300
```
### 3.類別屬性(Class Attribute)
定義:各自物件共享類別屬性,類別屬性修改,各自物件之屬性一起修改
```python=
class Banks():
location = "Taiwan"
def __init__(self, uname):
self.name = uname #public==>他人可以查詢得到
self.balance = 0
self.bankname = "Taipei Bank"
def save_money(self, money):
self.balance += money
print("save ", money, "Finish")
def withdraw_money(self, money):
self.balance -= money
print("draw ", money, "Finish")
def get_balance(self):
print(self.name, "Rest: ", self.balance)
bank1 = Banks('Joseph')
bank2 = Banks('Emma')
print("original location:", bank1.location) #Taiwan
print("original location:", bank2.location) #Taiwan
Banks.location = "America"
print("New location:", bank1.location) #America
print("New location:", bank2.location) #America
```
### 4.屬性(Property)
定義:可控制類別中的屬性,並且可以用方法(method)來設定規則
```python=
#範例需求:Bank名字可以修改,但是要為字串
class Banks():
location = "Taiwan"
def __init__(self, uname):
self.name = uname #此處還是為public,後方則為private
self.__balance = 0
self.__bankname = "Taipei Bank"
@property
def name(self):
# print('get name')
return self.__name
@name.setter
def name(self, new_name):
# print('set name')
if type(new_name) == str:
self.__name = new_name
else:
raise TypeError('name need str.')
def save_money(self, money):
self.__balance += money
print("save ", money, "Finish")
def withdraw_money(self, money):
self.__balance -= money
print("draw ", money, "Finish")
def get_balance(self):
print(self.__name, "Rest: ", self.__balance)
bank1 = Banks('JOJO')
print(bank1.name) #JOJO
bank1.name = 'Emma'
print(bank1.name) #名字修改成Emma
```
## 封裝(encapsulation)
將類別內attribute/method私有化,class外部無法使用內部資訊
使用方法:在attrubute/method前面加上"__"
```python=
#函數私有化==>__XXX
class Banks():
def __init__(self, uname):
self.__name = uname #private==>私有化內容
self.__balance = 0
self.__bankname = "Taipei Bank"
def save_money(self, money):
self.__balance += money
print("save ", money, "Finish")
def withdraw_money(self, money):
self.__balance -= money
print("draw ", money, "Finish")
def get_balance(self):
print(self.__name, "Rest: ", self.__balance)
bank1 = Banks('Joseph')
bank1.save_money(300) #save 300 Finish
bank1.__name = 'JoJo' #經過封裝後修改無效化
bank1.get_balance() #Joseph Rest: 300
bank1.withdraw_money(300) #draw 300 Finish
bank1.get_balance() #Joseph Rest: 0
```
## 繼承(inheritance)
attribute/method可以被繼承
繼承者:子類別(subclass)
被繼承者:父類別(superclass)
```python=
class Banks():
def __init__(self, uname, money):
self.name = uname #public==>他人可以查詢得到
self.balance = money
self.bankname = "Taipei Bank"
def get_balance(self):
print(self.name, "has: ", self.balance)
return self.balance
class Daan_Banks(Banks): #Daan_Banks == subclass
pass #Banks == superclass
bank1 = Banks('Joseph', 1000)
bank1.get_balance() #Joseph has: 1000
```
### 多重繼承
```python=
class Grandfather():
def action1(self):
print("I'm grandfather.")
class Father(Grandfather):
def action2(self):
print("I'm father.")
super().__init__()
class Uncle(Grandfather):
def action3(self):
print("I'm uncle.")
super().__init__()
class Son(Father, Uncle):
def action4(self):
print("I'm son.")
super().__init__()
son = Son()
son.action1() #I'm grandfather.
son.action2() #I'm father.
son.action3() #I'm uncle.
son.action4() #I'm son.
```
## 多型(polymorphism)
預設狀態子類別會繼承父類別,但若子類別method與父類別相同,會覆寫父類別method
```python=
class Animals():
def __init__(self, animal_name):
self.name = animal_name
def which(self):
return 'Name:'+ self.name.title()
def action(self):
return 'sleeping'
#有繼承
class Dogs(Animals):
def __init__(self, dog_name):
super().__init__(dog_name.title())
def which(self):
return 'Name:'+ self.name.title()
def action(self):
return 'eating'
#無繼承
class Cats():
def __init__(self, cat_name):
self.name = 'Name:' + cat_name.title()
def which(self):
return self.name
def action(self):
return 'playing'
def do(obj):
print(obj.which(), '', obj.action())
bear = Animals('JOJO')
do(bear) #Name:Jojo sleeping
dog = Dogs('DOGGY')
do(dog) #Name:Doggy eating
cat = Cats('Catty')
do(cat) #Name:Catty playing
```
# :memo: try/except
使用時機:當執行程式時,可能會產生預期之外之行為,可使用try/except語法解決
```python=
#使用前
def divison(a, b):
return a / b
print(divison(3,0))
#ZeroDivisionError: division by zero
#使用後
def divison(a, b):
try:
return a / b # None
except (ZeroDivisionError) as e:
print('[Error]: Divisor can not be zero.')
print(e)
print(divison(3,0))
# [Error]: Divisor can not be zero.
# division by zero
# None
```
## Raise語法
用Raise顯示Exception
```python=
def chkPWD(pwd):
pwdlen = len(pwd)
if pwdlen > 6:
raise Exception('password is too long.')
if pwdlen < 4:
raise Exception('password is too short.')
else:
print('password correct!')
for pwd in ('abcdefg', 'abc', 'abcd'):
try:
chkPWD(pwd)
except Exception as err_msg:
print('Error occurs during password checking: ', str(err_msg))
# 所有皆有執行
# Error occurs during password checking: password is too long.
# Error occurs during password checking: password is too short.
# password correct!
```
## Assert語法
Assert可以幫助檢查變數是否符合期望,若不符合則產生例外
```python=
def chkPWD(pwd):
pwdlen = len(pwd)
assert pwdlen > 6, 'password is too long.'
assert pwdlen < 4, 'password is too short.'
print('password correct!')
print(chkPWD('abc'))
# 產生執行錯誤
# AssertionError: password is too long.
```
# :memo: 檔案處理(讀入、寫入)
## txt, csv檔案
CSV檔案為常見的資料儲存格式
定義:row之間用換行來區分,column用" ,"來區分

### open()
1.讀檔
[Documentation: open()](https://docs.python.org/3/library/functions.html#open)
```python=
#open後一定要close
path = "stock.csv"
f = open(path, "r", encoding = "UTF-8")
print(f.name) #stock.csv
print(f.closed) #False
print(f.mode) #r
f.close()
print(f.closed) #True
```
```python=
#with as用法可以省略
with open('stock.csv', 'r', encoding="UTF-8") as f:
data1 = f.read()
print(data1)
# Code,Name,Close Price,Change Percent,Today Amount,Last Day Amount,Last 2Day Amount
# 2303,聯電,52.7,1.35,3967.0,5606.0,-2319.0
# 3545,敦泰,270.5,9.96,3012.0,962.0,227.0
# 2454,聯發科,933.0,1.52,1740.0,1547.0,-599.0
# 2603,長榮,154.0,7.32,1510.0,240.0,-9557.0
# 2338,光罩,101.5,6.06,1272.0,-624.0,907.0
# 2609,陽明,145.5,3.56,1260.0,-1026.0,-2362.0
# 2002,中鋼,36.3,3.12,1143.0,595.0,-970.0
# 1101,台泥,53.0,1.73,725.0,-216.0,138.0
# 2409,友達,20.7,5.08,708.0,-419.0,195.0
# 8261,富鼎,124.5,6.87,519.0,-19.0,-18.0
```
```python=
#readlines() 每一行列成list
with open('test1.txt', 'r', encoding="UTF-8") as f:
data1 = f.readlines()
print(data1)
#['Python is powerful and fast;\n', 'plays well with other;\n', 'is open.']
```
2.寫檔
```python=
path = "test1.txt"
f = open(path, "w", encoding = "UTF-8")
txt = '''Python is powerful and fast;
plays well with other;
is open.'''
f.write(txt)
f.close()
# Python is powerful and fast;
# plays well with other;
# is open.
```
```python=
#with as用法可以省略
txt = '''Python is powerful and fast;
plays well with other;
is open.'''
with open('test1.txt', 'w', encoding="UTF-8") as f:
data1 = f.write(txt)
# Python is powerful and fast;
# plays well with other;
# is open.
```
### Excel
# :memo: Internal Module
## 1. re module (Pattern正規化)
用法:用來抓取符合規定規則之字串


### **re.match()**
比對從第一字元開始是否與pattern相符(只要有一個地方錯就None)
```python=
import re
txt = 'hello, hey, hi, Salaheyo'
x = re.match('\w*', txt) # \w == [a-z, A-Z, 0-9], * == 任意個數之character
print(x) #<re.Match object; span=(0, 5), match='hello'>
x = re.match('\w{5}, \w{2}', txt)
print(x) #<re.Match object; span=(0, 9), match='hello, he'>
```
```python=
import re
phonenumber = "02-222-1234, 03-333-1234"
regex = "(\w{2})-\w{3}-\w{4}"
x = re.match(regex, phonenumber)
if x:
print(x) #<re.Match object; span=(0, 11), match='02-222-1234'>
print("Valid phone number")
else:
print("Invalid phone number")
#Valid phone number
```
```python=
import re
phonenumber = "(02)-222-1234, 03-333-1234"
regex = "(\w{2})-\w{3}-\w{4}"
x = re.match(regex, phonenumber)
if x:
print(x) #<re.Match object; span=(0, 11), match='02-222-1234'>
print("Valid phone number")
else:
print("Invalid phone number")
#Invalid phone number
```
如果要完整比對需要在結尾加$
```python=
import re
list1 = ['AB1234', 'A01234', '0A1234', '1234AB', '1234A0', '123401', '0A1234', 'BMW2299', 'ABC123', 'AB123']
regex = r'\d{4}\w{2}$|\w{2}\d{4}$|[A-Z]{3}\d{4}$' # 防止跳脫字元
for i in range(len(list1)):
if re.match(cl_pattern, list1[i]):
print("normal: ", list1[i])
else:
print("Fail: ", i)
```
### **re.search()**
搜尋任何有符合pattern的字串
```python=
import re
txt = 'Surprise mother fucker'
x = re.search(f'mother', txt) #f'XXX'表示''為字串
print(x)
print(type(x))
```
```python=
import re
phonenumber = "(02)-222-1234, 03-333-1234"
regex = "\w{2}-\w{3}-\w{4}"
x = re.search(regex, phonenumber)
if x:
print(x) #<re.Match object; span=(15, 26), match='03-333-1234'>
print("Valid phone number")
else:
print("Invalid phone number")
#Valid phone number
```
### **re.findall()**
搜尋任何所有滿足pattern的字串
```python=
import re
txt = 'hello! 23 hi 111. how are 889.'
pattern = '\d+' #\d == [0-9], + ==至少一個
x = re.findall(pattern, txt)
print(x) #['23', '111', '889'] type=<list>
```
```python=
import re
phonenumber = "02-222-1234, 03-333-1234"
regex = r"\d{2}-\d{3}-\d{4}" #r"xxx",方便解除內部跳脫字元
x = re.findall(regex, phonenumber)
if x:
print(x)
print("Valid phone number")
else:
print("Invalid phone number")
#['02-222-1234', '03-333-1234']
#Valid phone number
```
```python=
import re
ntu_id = "R05543049, B12345678, C87654321"
regex = r"(\w{1}[0|1]\d{7})" #[1|2]表示有1 or 2
obj = re.findall(regex, ntu_id)
if obj:
print(obj)
print("Vaild id number")
else:
print("Invaild id number")
#['R05543049', 'B12345678']
##Vaild id number
```
## 2. collections
[collections - 容器資料型態](https://docs.python.org/zh-tw/3/library/collections.html)