<style>
.right_text{
text-align:right;
font-size:13px;
padding-bottom: 50px;
}
</style>
<div class="right_text">
<p>贊助我:</p>
<a href="https://www.buymeacoffee.com/Hoshiyomi" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
</div>
## 摘要
* 基礎語法:變數與變數型態,運算子,陣列與元組,基本輸入輸出,條件句
* 進階語法:迴圈,函式,物件,物件繼承,例外處理
## 虛擬環境
### GNU/Linux
確定python已經裝好:
:::spoiler Debian/Ubuntu
```
sudo apt-get python3
```
:::
:::spoiler Arch
```
sudo pacman -S python3
```
當然也可以使用`yay -S python` 或是其他AUR helper
:::
在專案的directory輸入`python -m venv .venv`,此指令會生成一個`.venv`的資料夾,裡面會有啟動虛擬環境的執行檔以及`pip`。
`source .venv/bin/activate`來啟動虛擬環境,這樣就可以不需透過系統的package manager來安裝python的module。
## 基礎語法
### 變數(Variable)
變數即為某部分記憶體儲存的資料
變數取名法:
通常用有意義的字
比如:
`numbers`、`words`
如果需要多個英文字
`input_choices`、`inputNumbers`
注意不可以與`python`內建的關鍵字衝突
常見關鍵字:
`if`、`elif`、`else`、`for`、`while`、`try`、`except`
`break`、`continue`、`in`、`True`、`False`、`def`、`None`
`global`、`return`
### 進制
`0x`表示16進位
`0o`表示8進位
```python=
print("%d %x %o" % (12, 0x12, 0o12))
print("%d %x %o" % (12, 12, 12))
```

### 型態(type)淺說
「型態」為資料在電腦中儲存的一個標籤,這個標籤決定了資料間能否互相運算或是使用特定功能。
比如:`int`即表示整數型態,他能夠和各種數字型態相加減,但是所得的結果的型態可能會改變
> `int(+-*)int=int`
> ***`int(/)int=float`***
> `int(+-*/)float=float`
> `float(+-*/)int=float`
> 判斷技巧:跟`float`扯上關係就回不去`int`了
第二行的結果說明:
雖然`1/1`顯然可以寫成`1`,但表示為比例的那一刻就成為了有理數。

> `type(變數)`將回傳變數的型態
事實上,各種基本型態是python內建函式庫中的模組(Module)
每個Module都有自己的標籤
基本型態表:
| Type | int | float | str(string) | bool |
| :----: | :----------------------: | :----------------------------: | :----------: | :---: |
| 說明 | 與數學$\mathbb{Z}$相同 | 任意實數皆會被近似成有限小數 | 字串 |True or False|
> 在`python`中,轉換型態的方法為
> `變數型態()`
> 比如:`print(float(2))`、`print(int(3.5))`
> 
> 變數型態的不同將會使輸出結果不同
> 無法轉換時會報錯
> 若要換行輸出可在字串內加入`\n`
> 例如`'你為什麼不問問神奇海螺呢?\n這裡還有沒有第五個章魚哥'`
> 
### 運算子operators
數學運算子Mathematical operators
| 語法 | + | - | * | / | % |
| :----------: | :----------: | :----------: |:--------: | :--------: | :--------: |
| 名稱 | 加 | 減 | 乘 | 除 | 取餘數 |
| 運算方向 | 由左至右 | 由左至右 | 由左至右 | 由左至右 | 由左至右 |
| 回傳 | 物件相加 |物件相減 |物件相乘|物件相除|左除以右的餘數(限定數字運算)|
| 運算優先度 | 在乘除之後 | 在乘除之後 | 最優先 | 最優先 | 最優先 |
邏輯運算子[^first]Logical operators
| 語法 | `&&`、`and` | \|\|、`or` | `!`、`not`[^second] | == |
| :----------: | :-----------: | :----------: | :----------: | :----------: |
| 名稱 | 且 | 或 | 不 | 等於 |
| 運算方向 | 由左至右 | 由左至右 | 由左至右 | 由左至右 |
| 運算優先度 | 在加減之後 | 再加減之後 | 在加減之後 | 在加減之後 |
[^first]: 邏輯運算子回傳的值皆為布林值
[^second]: `!=`即為`==`的否定敘述
> 布林值可表示為`0或1`,其中`True`表示`1`,`False`表示`0`
邏輯運算子的真值表:
`&&`:
| A | B | output |
| :---: | :---: | :------: |
| 0 | 0 | 0 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 1 | 1 |
> 電路接法:串聯
`||`:
| A | B | output |
| :---: | :---: | :------: |
| 0 | 0 | 0 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 1 | 1 | 1 |
> 電路接法:並聯
`!`:
| A | output |
| :---: | :------: |
| 0 | 1 |
| 1 | 0 |
> 若需要強迫電腦優先運算某些敘述,可以用小括號包含
> 中括號與大括號另有其涵義
> 各物件都有自己本身支持的運算子,在使用之前應該先看過API文件
賦值運算子[^third]
\=
[^third]:`a=a+1`可寫為`a+=1`,`a=a-1`可寫為`a-=1`,乘除同理
名稱:賦值
運算方向:由右至左
比如:
```python=
a=2
#a is now 2
a=a+2
#a先取原本的值加上2後再把結果傳給a儲存
```
運算優先度:最後
### 陣列`list`
什麼是陣列?
舉例:
```python=
list1 = ['水果','香蕉']
list2 = [0, 3, 5]
```
陣列就是一串資料,每個資料都有一個自己的索引值(`index`)
陣列中每個元素都是一個變數,意思是可以儲存各種不同型態的物件
比如:
```python=
from typing import List, Union
#此模組是為了方便說明陣列中儲存的資料型態
#非必要
#也可以讓編譯器知道要顯示什麼Object method或attribute
#就可以不需要背那麼多指令
#List使用方法:List[object]
#List意義:說明陣列中元素的資料型態
#Union使用方法:Union[object1,object2,...]
#Union意義:型態的「集合」,就是裡面會有各種不同的型態
list1:List[Union[str,int,float]] = [1,'abc',3.7]
```
陣列的各種功能:
首先先了解Class method(類別功能)
`object().func()`
就是一個`class`中自帶的功能
```python=
list1 = [3,2,1,3,4,2,7,1,10]
#=====插入元素=====
list1.append(3)
#在陣列尾端插入3的元素
list1.insert(3,5)
#在陣列索引值為3的地方插入5的元素
#=====刪除元素=====
list1.pop(3)
#刪除索引值為3的元素
list1.remove(4)
#刪除由左到右第一個出現4的元素
#=====陣列內建函數=====
#陣列長度函數:
len(list1)
#陣列最大值:
max(list1)
#陣列最小值
min(list1)
#=====其他功能=====
#反轉陣列:
list1.reverse()
#將陣列的數值做排序
list1.sort()
#(不推薦使用因為速度太慢)
#詳情參考排序法
#快速排序法&氣泡排序法
#(推薦自己寫quicksort)
```
#### 多維陣列
常常陣列不只有單單一行,這樣能夠存放的資料太少。
因此自然出現了多維陣列。
實際上多維陣列只不過是陣列中每個元素都是一個陣列。
```python=
list_2D = [[3,5],[44,1],[2,29],[4,23]]
print(list_2D[2][0])
#29
print(list_2D[0][2])
#5
```
> 陣列事實上跟矩陣是一樣的東西
以上陣列作成表格:
| index | 0 | 1 | 2 | 3 |
|:-----:|:---:|:---:|:---:|:---:|
| 0 | 3 | 44 | 2 | 4 |
| 1 | 5 | 1 | 29 | 23 |
可以對應到以下矩陣:
$\begin{bmatrix}3&44&2&29\\5&1&29&23\end{bmatrix}$
### 元組`Tuple`
```python
tuple1 = ('e', 2.7182818)
tuple2 = ('黃金比例', 1.618)
```
跟陣列幾乎一樣,但是是小括號的
通常使用在將具有對應關係的資料包起來
> 不能修改元素(不會造成資料遺失)
> 執行速度快
### 基本輸出輸入(I/O)(input/output)
輸出`print()`
語法:
`print(object)`
功能:在終端機上輸出文字
比如:
```python=
print('Hello world')
print(1+1)
print('1'+'1')
print()
print(type(1/3))
print('1','2')
```
執行結果:
結果說明:
第一行為直接輸出字串
第二行為輸出`1+1`的結果
第三行為輸出兩字串`'1','1'`的相加結果
第四行為輸出空行
第五行為輸出$\dfrac{1}{3}$在`python`中的型態
第六行為輸出`'1'`和`'1'`中間使用空格隔開

> 逗點即為分開輸出
> 字串與字串間能相加但不能相減
> 字串是一種陣列(`list`)
輸入`input()`
語法:`input(str)`
比如:
```python=
a=input('輸入身高(公分)\n')
a=float(a)/100#轉換為數值型態才能與數字做運算
print('你的身高為'+str(a)+'公尺')
```

> `input()`括弧中若沒有填入字串,則不會輸出任何東西
> `input()`會等到使用者輸入字詞時才結束
功能:回傳使用者在終端機上的輸入(回傳型態為str)
### 條件句`if,elif,else`
語法:
```python=
condition1 = (1==1)and(2<=3)
condition2 = #...
if condition1:bool:
#...
elif condition2:bool:
#...
else:
#...
```
功能:
一組`if-elif-else`由上到下檢驗
1. 若第`n`個條件未成立,則判斷第`n+1`個條件是否成立。
2. 只要有一條件成立,則只執行其條件內的敘述,不執行其他的敘述。
3. 若所有條件句都為假,則在存在`else`的前提下執行`else`的內容(default function)。
4. `elif`、`else`皆為optional。
5. `elif`可以有無窮多個
比如:
```python=
a = 50
b = 30
if a+b <= 100:
a=a+2
b=b*2
elif a+b <= 80:
a=3
b=2
else:
a=7
b=0
print(a,b)
```
結果說明:
因為在第一行中,`a+b<=100`已經成立,故執行`if`內的敘述之後
跳到輸出`a,b`
因此結果為52 60

實作:
範例1:簡易加法計算機
題目敘述:
輸入有一行,包含兩個整數$-2^{32}<a<2^{32}$與$-2^{32}<b<2^{32}$,一個運算符號$+$
輸出其數學上的結果
範例輸入:1+1
範例輸出:2
參考解答:
```python=
print(sum(map(int, input().split())))
```
> 字串型態有一個功能叫做`.split(str)`
> 其功能為:在字串中尋找括弧內的字元,以之為中心將字串分解成兩個部分
> 例如
> ```python=
> string = '1986-06-04'
> string = string.split('-')
> print(string)
> ```
> 
> 其輸出為一陣列
> 如果沒有括弧中的字元則會回傳一個`list`
> 其中只有一個元素為原本的字串
範例2:計算BMI
題目敘述:給定兩數h與w分別代表身高(公尺)與體重
輸出其BMI值,並四捨五入至小數點後2位
(BMI=$\dfrac{w}{h^2}$)
參考解答:
```python=
h = input()
w = input()
h = float(h)
w = float(w)
bmi = w/(h*h)
print(round(bmi,2))
```
範例3:線性搜尋法
給定一群數字(已經由小排到大),輸出指定數字的索引值,若無則輸出「無此數字」
```python=
list1 = [1,2,4,10,17,18]
target1 = 10
target2 = 3
print(list1.index(target1) if target1 in list1 else "無此數字")
print(list1.index(target2) if target2 in list1 else "無此數字")
```
---
## 進階語法
### 迴圈:
迴圈分為`for`迴圈與`while`迴圈
`for`迴圈
語法:
```python=
for var in iter:
#...
```
功能:
將`in`後方的`iter`(能夠迭代的物件)將其元素逐一取出存入`var`
`var`是可以自行取名的變數
`iter`的說明
https://vivi.emmphysics.com/%E6%90%9E%E6%B8%85%E6%A5%9Apython%E4%B8%AD%E7%9A%84iterable%E3%80%81iterator%E5%92%8Cgenerator%EF%BC%88%E4%B8%80%EF%BC%89/
> 典型的`iter`物件就是陣列
> 事實上`str,tuple,dict`都可以視為陣列的一種,等等會再提到
常與`for`迴圈使用的函數
```python=
range(start:int,stop:int,step:int)
#start and step is optional(選填參數)
#start has a default value of 0(預設值為0)
#step has a default value of 1(預設值為1)
#range()是一個物件,他會回傳一個陣列
#例如range(0,5)->[0,1,2,3,4]
enumerate(sequence:iter[,start:int = 0])
```
`enumerate()`功能說明
```python=
list1 = ['a','b','c']
print(list(enumerate(list1)))
```

就是將每個元素變成`(index,object)`的`tuple`形式
比如:
計算
$\displaystyle\sum_{k=1}^{30}(2k-1)=?$
```python=
sum = 0
for i in range(30):
sum += 2*(i+1)-1
```
範例5:氣泡排序法
題目敘述:給定一群實數,將其由大到小排序。
思考:將陣列由前到後檢查,若第n+1項大於第n項,則將第n+1項的值與第n項交換
因為每次交換後,最後一筆資料必定會是正確的,因此需要檢查$\dfrac{n(n-1)}{2}$次
```python=
list1 = [33,22,1,5,10,0,-4,3]
n = len(list1)
while n > 1:
n-=1
for i in range(n):
if list1[i+1] > list1[i]:
list1[i+1], list1[i] = list1[i], list1[i+1]
print(list1)
```
但python的list物件有內建一個函式能夠直接排序。
```python=
list1 = [33,22,1,5,10,0,-4,3]
print(list1.sort())
```
```python=
list1 = [33,22,1,5,10,0,-4,3]
n = len(list1)
while n > 1:
n-=1
for i in range(n):
if list1[i+1] > list1[i]:
list1[i+1], list1[i] = list1[i], list1[i+1]
print(list1)
list1 = [33,22,1,5,10,0,-4,3]
list1.sort(reverse=True)
print(list1)
```
輸出結果:

範例6:https://zerojudge.tw/ShowProblem?problemid=a216
範例7:判斷是否為整數
題目敘述:給定一實數,若為整數則輸出`True`,否則輸出`False`
思考:所有整數即為方程式$x-[x]=0$的解
```python=
from math import floor
x = input()
if float(x) - floor(float(x)) == 0 :
print('True')
else:
print('False')
```
### 函式Function
何謂函數?一種對應關係。
數學上的函數定義為:
$f:A\to{B}$
其中$f$是一種運算規則,將$A$集合的數值對應到$B$集合
多元函數就是具有很多自變數的函數($f(x_1,x_2,x_3...x_k)$)
> 程式設計中,函數不一定會回傳值(void function),只會做特定的事情
`python`中,函數的定義方法如下
```python=
def func(argument1, argument2):
#...
return #...
```
其中`return`可有可無,運行至`return`時將會直接結束函數的運行並回傳值。
回傳值可以是任何型態,甚至可以回傳另一函數。
比如:
```python=
def add_1(number):
number -= -1
return number
def choose_something(cases:int):
if cases == 1:
return 'hello world'
elif cases == 2:
return add_1(2.14159)
elif cases == 3:
return add_1
elif cases == 4:
return ('Never', 'Gonna', 'Give', 'You', 'Up')
elif cases == 5:
list1 = ['Never', 'Gonna', 'Give', 'You', 'Up']
return " ".join(list1)
else:
return 'No such option...'
for i in range(1,7):
print(choose_something(i))
```
輸出:

參數設定:
預設值
```python=
def func(arg = "default value"):
pass
# or
from typing import Optional
def func2(arg:Optional[type]):
pass
# which sets the default value to None
# notice that all arguments with default value
# should be declared after those with no default value.
```
keyword arguments and postional arguments
```python=
def func(first_name:str, last_name:str):
return "Hi!" + first_name + last_name
print(func("elon", "musk"))
print(func(last_name = "musk" ,first_name = "elon"))
# using keyword makes less error.
```
Variable length arguments
```python=
def func(*x):
# x is some data, which we don't know how long it is.
pass
```
Variable keyword arguments
```python=
def func(**kwargs):
for i in kwargs.values():
...
pass
func(sunday = 7, monday =1, ...)
```
unpacking arguments
```python=
list1 = [1,2,3,4,5]
print(*list1)
#this would print 1 2 3 4 5 on console
def func(**kwargs):
for i in kwargs:
print(f'{i} = {kwargs[i]}')
dict1 = {"Hi":1, "hi":2}
func(**dict1) # this is also equivalent to func(Hi =1, hi=2)
# this would print
# Hi = 1
# hi = 2
```
應用:
> 為何需要函數?複製貼上不就好了嗎?
> 函數能夠把程式中某些重複程序收集起來,使用時再呼叫的工具。
> 若是使用複製貼上,當這個功能寫錯,需要改變某些程式碼,你可能已經複製貼上了幾百次這幾個固定的程式碼,現在就必須每段程式碼都要改,效率非常低。
> 因此若是使用函數將重複程序收集起來,能夠快速地`debug`,也能夠增加程式的可閱讀性。
```python=
def find_digit(number:int):
digit = 0
while number > 1:
digit += 1
number /= 10
return digit
a = input('輸入正整數1')
b = input('輸入正整數2')
c = input('輸入正整數3')
print(find_digit(a),find_digit(b),find_digit(c))
```
> 小技巧:在不知道程式哪邊出問題時可以`print()`各種參數或是字串
> 例如:想要輸出`foo(1)`為3卻沒有反應
> ```python=
> def foo(x):
> if x>1:
> return 2
> elif x<1:
> return 3
> print(foo(1))
> ```
> 將不會輸出任何東西
> 因此在各個`if-elif`判斷式中加上`print(...)`確認是跑進哪個條件式中
> 在最外面也加上`print(...)`以確認有執行`foo()`函式
> ```python=
> def foo(x):
> print('a')
> if x>1:
> print('b')
> return 2
> elif x<1:
> print('c')
> return 3
> print(foo(1))
> ```
> 輸出理論上要有一個a和一個c,但卻只有輸出a,表示`elif x<1:`這個判斷式有問題
> 因此修改為`elif x<=1:`則程式就可以正常運行了。
### 自動化測試
```python=
#code
def test_func(args,...):
#testing all function
#can use assert func() == expect output to check
pass
if __name__ == "__main__":
test_func()
```
直接跑此`.py`檔案才會測試功能,若被當成`module` import則不會測試。
### lambda functions
`lambda arg1,arg2...:expression`
also known as anonymous function
```python=
def play_source(self,voice_client:VoiceClient):
source = FFmpegPCMAudio(self.queue[self.song_idx]["local_path"])
voice_client.play(source, after = lambda e: print('Player error: %s' % e) if e else self.next_song())
```
`lambda e: print(f"Player error: {e}") if e else self.next_song()`
### map and filter
```python=
t = map(f,seq1,seq2,...)
# [f(seq1[i],seq2[i],...) for i in range(min(len(seq1),len(seq2),...))]
```
```python=
t = filter(f,seq)
# [x for x in seq if f(x)]
```
### 物件Object
物件的概念:
生活中每個東西都有自己的功能與屬性(通常為外觀)
以下拿手機作為舉例
比如手機可以打電話、玩遊戲、看影片、聽音樂。這樣的「功能」可以對應到程式設計中「物件方法(method)」的概念。
而手機可以自己設定桌面背景、選擇手機顏色、要不要加上手機殼或是配件。這樣能夠做更改的變數對應到程式設計中「物件屬性(attribute)」的概念。
在`python`中,物件的宣告通常是使用`class`關鍵字
中文名稱為「類」
範例:
```python=
class Smartphone:
def __init__(self, shell = None, color = 'white', desktop_image = 'image.png'):
#物件的初始化函數
#(init stands for initialize)
#當物件產生時會被執行
#通常是設定參數
self.shell = shell
self.color = color
self.desktop_image = desktop_image
self.user_name = 'Steve'
self.number = '09123456781'
self.internet_connected = True
def call_someone(self, contactant):
#宣告物件方法(也是一種函數,只是只能透過這個物件存取)
#self是用以存取本身資料的一個參數
#透過self能夠存取到目前當下物件的各種狀態
call(contactant.number)
def play_game(self, game):
game_open(game)
game.run()
#...
#產生物件
phone1 = Smartphone(shell = '犀牛盾', color = 'black', desktop_image = 'default.png')
#使用物件方法
phone1.call_someone(contactant = 'Alex')
#改變物件屬性
phone1.user_name = 'John'
phone1.desktop_image = 'Rickroll.png'
```
使用物件的話就可以大量生產製造重複的東西,但又保有能夠客製化的選項。
因為產生物件時只能使用其對外公開的參數與功能,物件的內部函數是如何寫的也能保有隱蔽性,不易被抄襲。
`class`對程式的速度影響小,且能夠增加程式可讀性,也因此在寫大型`project`時通常都會使用大量的物件,也就發展出了所謂的「物件導向」程式,例如`Java, JavaScript`。
```python=
class Smartphone:
def __init__(self, shell = None, color = 'white', desktop_image = 'image.png'):
#物件的初始化函數
#(init stands for initialize)
#當物件產生時會被執行
#通常是設定參數
self.shell = shell
self.color = color
self.number = '09123456781'
def call_someone(self, contactant):
#宣告物件方法(也是一種函數,只是只能透過這個物件存取)
#self是用以存取本身資料的一個參數
#透過self能夠存取到目前當下物件的各種狀態
call(contactant.number)
def play_game(self, game):
game_open(game)
game.run()
@property
def set_desktop_image(self, image):
try:
with open(image, "rb"):
#...
self._desktop_image = image
return print("Done!")
except :
return print("Error!")
username = property(lambda self:self._username, \
lambda self, name: self._username = username)
# you can set property by using class.__dict__["name"]
```
#### 子類subclasses
有些物件具有大量的屬性,這時候就可以使用子類來將「具有相同特性的屬性」分類
這也能夠大幅提升程式的可讀性。
範例:
```python=
class MySqlDataBase:
class SqlInfo:
#此即子類,設定MySql執行時需要使用的各種參數
def __init__(self, host, user, password, database):
self.host = host
self.user = user
self.password = password
self.database = database
def __init__(self):
self.SqlInfo.host = host
self.SqlInfo.user = user
self.SqlInfo.password = password
self.SqlInfo.database = database
#雖然現在看起來創建子類並沒什麼意義,但是也許之後會加上其他屬性,因此先保留著
def connect_to_db(self):
db = mysql.connector.connect(
host = self.SqlInfo.host,
user = self.SqlInfo.user,
password = self.SqlInfo.password,
database = self.SqlInfo.database
)
return db
def get_db_data(self, sql_cmd:str, values:tuple = ()):
db = self.connect_to_db()
cursor = db.cursor()
cursor.execute(sql_cmd, values)
return cursor.fetchall()
def insert_data(self, sql_cmd:str, values:tuple):
db = self.connect_to_db()
cursor = db.cursor()
cursor.execute(sql_cmd, values)
return db.commit()
def del_data(self, sql_cmd:str, values):
db = self.connect_to_db()
cursor = db.cursor()
cursor.execute(sql_cmd, values)
return db.commit()
def update_data(self, sql_cmd:str, values:tuple):
db = self.connect_to_db()
cursor = db.cursor()
cursor.execute(sql_cmd, values)
return db.commit()
```
### 物件繼承Inheritance
何謂繼承?
法律上的繼承:一個人死亡後將自己的遺產交給其子孫的行為
物件導向程式設計中,物件並不會「死亡」,只保留了「將自己的遺產交給子孫」的特性,被繼承的物件稱為父類,繼承的物件叫做子類
我們可以利用「繼承」將物件中的資料傳給另一物件,方法如下:
```python=
import discord
from discord import View
class GameSelect(View):
#繼承View物件
def __init__(self):
super().__init__(timeout = None)
#super()是用來繼承整個物件中的某些函式
class joinGame(View):
def __init__(self, main:GameSelect):
super().__init__(timeout = None)
self.main = main
#將GameSelect當成參數傳入,也能達到繼承的效果
#...
```
> 繼承通常用在需要一堆物件共享同一堆資料的時候
> 例如以下
```python=
class car:
def __init__(self, color= 'red', length = 200, width = 180, height = 180):
self.color = color
self.length = length
self.width = width
self.height = height
class car_computer(car):
def __init__(self):
super().__init__()
class car_computer_super_sonic_sensor(car_computer):
def __init__(self, distance):
super().__init__()
self.distance = distance
def get_distance(self):
#能夠測距離的程式
```
### 例外處理Exception
當我們在執行程式時,常常會遇到某些我們不想要處理的情況,這時就可以使用例外處理的方法。
```python=
from sys import stdin, float_info
from math import floor
def plus_one(string):
try:
string_int = float(string)
if abs(floor(string_int) - string_int) < float_info.epsilon:
return print(f'{string}+1={string_int+1}')
else:
raise TypeError
except:
return print('你輸入的不是整數!')
for string in stdin:
plus_one(string)
```
此段程式會將使用者輸入的字串先轉為數值之後再加上1
而當使用者輸入非整數或文字時,將會輸出「你輸入的不是整數!」以免程式卡住。
> Early return technique:
> 在執行程式時,使用者的輸入常常會有多種可能,而初學者的作法都是使用很多巢狀的if-else加上try-except敘述。
> 例如:
```python=
message_recieve = True
async def on_message(message):
if message_recieve:
if message.guild != None:
if message.guild.id == 910150769624358914:
me = self.client.get_user(Me)
msg = 0
if len(message.stickers) != 0:
msg = await me.send(f'{message.author.display_name} 在 {message.channel.name}中說 : \n{message.content}並傳送了貼圖:{message.stickers[0].url}')
else:
msg = await me.send(f'{message.author.display_name} 在 {message.channel.name}中說 : \n{message.content}')
if len(message.attachments)>0:
for i in message.attachments:
file = await i.to_file()
return await msg.add_files(file)
if len(message.embeds)>0:
return await msg.edit(embeds=message.embeds)
```
> 但這會使得程式碼難以閱讀
```python=
message_recieve = True
async def on_message(message):
if not message_recieve:
return
if message.guild == None:
return
if message.guild.id != 910150769624358914:
return
me = self.client.get_user(Me)
msg = 0
if len(message.stickers) != 0:
msg = await me.send(f'{message.author.display_name} 在 {message.channel.name}中說 : \n{message.content}並傳送了貼圖:{message.stickers[0].url}')
else:
msg = await me.send(f'{message.author.display_name} 在 {message.channel.name}中說 : \n{message.content}')
if len(message.attachments)>0:
for i in message.attachments:
file = await i.to_file()
return await msg.add_files(file)
if len(message.embeds)>0:
return await msg.edit(embeds=message.embeds)
```
> 越少巢狀if-else敘述將可使程式碼較好閱讀,也可以提升一些執行速度
### 物件間的運算
{%gist xDDoubleTea/a6a4f6602e0ff216b988500a06d1c973 %}
在這裡的`Matrix`物件就支援了三種運算,加法減法與乘法
也就是創建的`Matrix`物件能夠透過原本的運算符號`+-*`直接做運算。