# 02 Accumulation ## Terminology :::success **Comments** ::: 下面是一個程式的示意圖 <br/> <br/> ```python def drawLSystem(self, snap): ''' makes the turtle draw out the result created by the createLSystem function ''' #complete this method state = [] for c in self.result: if c == 'F': snap.forward(self.distance) elif c == '+': snap.right(self.angle) elif c == '-': snap.left(self.angle) elif c == '[': save = {a : d for a,d in snap.__dict__.items()} state.append(save) elif c == ']': if state: load_state = state.pop() snap.__dict__ = load_state ``` Python認得空白鍵,而且用縮排來區分程式區塊,一般會用四個空白或一個 tab\ <br/> 程式裡還是會有要給人類看的部分,我們稱作 **comment** 或 **doc string**\ 如果一次要很多排,就會在前後加上 `'''`\ 如果只有單行,就會用 `#`\ 這些附註可以讓未來看自己寫的東西時,不會完全不懂 <br/> <br/> <br/> :::success **bool** ::: 在 Python 五花八門的內建 type 裡,有一種是幾乎所有程式語言都有的,那就是 boolean bolean 簡稱 bool 中文是布林,簡單來說,就是 `True` 和 `False`\ 電腦的世界只有 0 和 1,在這裡 0 是 `False`, 1 是 `True`<br/><br/> `bool` 是一種 **type**,這種 **type** 就只有 `True` 和 `False`\ 或代表 True 或 False 的變數<br/><br/> 布林的判斷是用兩個等於 **==**\ 不等於是 **!=**\ 大於等於 **>=**\ 小於等於 **<=**<br/><br/> 試試 ```python print(3 == 4) print(3 != 4) print(3 = 4) ``` `True` 就是會發生的事,`False` 就是不會發生的事<br/><br/> 在Python裡,所有亂七八糟的東西都是 True, 只有 `0`, `False`, `[]`, `""`, `None` 是 False<br/><br/><br/> :::success **Boolean operators** ::: 試試下面 ```python print(True and True) print(True and False) print(True or False) ``` :::spoiler 推敲出 `and` 和 `or` 的用法了嗎? <br/> `and` 要兩者都有才能成立\ `or` 只要一個成立就成立 ::: <br> 想想看下面會是什麼呢? ```python print(not(True and False)) print(True or False or False) ``` 還有許多其他的 Boolean operators 這邊就先不詳細介紹 <br><br> :::spoiler 依然不懂的話 快速,但原理不全然正確的理解方式還有:and 是乘法,or 是加法 所以既然 True 是 1,False 是 0,兩個變數用加法跟乘法得到的值就是最後的 boolean 值 別人的圖解如下 ![](https://i.imgur.com/X01jDzt.png) ![](https://i.imgur.com/p5ghlph.png) ::: --- <br> :::success **Member Functions or... Methods** ::: 之前介紹過各式各樣內建的 type,像是 `int` ,`str`, `float`, 也有說還有一種東西叫 `class`,之前的解釋是「 一個 object,可以理解成自己寫的一種 type」,其實這些內建的 type 也可以理解成一種 `class` ***Everything in Python is an object.*** 這就是物件導向 Object-oriented programming 糾結這些的意義在於知道他們的共通點與用法,而 `class`或說 objects 們的其中一種特性就是他們有自己旗下的 `function`,這些專屬於這種 type 的 function 叫作 **member functions** 或 **methods** (Python 裡叫 methods,但很多其他語言都叫 member functions 呼叫,或者說 call a function on an object 的方法是靠 `.` 試試 ``` python f = 3.14 my_str = "hello" print(f.is_integer()) print(my_str.islower()) print(my_str.isnumeric()) print(my_str.upper()) ``` 之前說 function 會有 return 的值,也就是函數 y = f(x) = ax + b 裡的 y 像是 `is_integer()` 回傳的值就是那一個 (限 float 的) object 能不能無痛變成 int,所以 return type 是 boolean `upper()` 回傳的就是那一個 (限 str 的) object 變成全部大寫的版本,所以 return type 是 string 關於 functions 或 methods 之後會再出現,目前先介紹怎麼使用內建的而已 <br> 至於 methods 當然還有很多很多可以用的,例如一個 string 就佔了這多: [Python documentation string methods](https://docs.python.org/3/library/stdtypes.html#string-methods) 所以寫程式時通常只會記得常見的,其他就 google 囉 --- ## Iteration 現在來介紹一些程式的重要元素 首先,先理解下面這段程式的意思 <br/> ```python a = 0 print(a) a = a + 1 print(a) a = a + 1 print(a) a = a + 1 print(a) a = a + 1 print(a) a = a + 1 print(a) ``` 會印出什麼呢? 簡單來說,有一個變數 a,被加了五次 1 \ 但這樣寫非常沒有意義,而且也很佔空間,於是在很多語言裡就出現 累加器 **Accumulator** \ 這邊介紹 `for` 和 `while` <br/> <br/> 這兩個東西都叫 迴圈 **loop** ,意思是不斷輪迴的東西\ 要介紹迴圈之前,我們先看兩個常常和和迴圈搭配的東西 `range` <br/> <br/> <br/> :::success **range** ::: `range` 就是範圍,是一種 class 用法如下 ```python range(0, 10, 2) #range(開頭, 結尾, 間隔) ``` 如果把上面 `range` 裡面的數字都印出來,會是0, 2, 4, 6, 8 `range` 會涵蓋開頭,但不包含結尾\ 當然,也有不用填滿三格的用法: ```python range(0, 10) #這個的間隔是 1 range(10) #開頭的預設是 0 ``` <br/> 想想看下面這些各含哪些數字 ```python range(10, 0) range(3, 11, 4) ``` ----- <br/><br/> :::success **Conditional Statements** ::: 現在我們來看假設句 `if`, `else`, `elif`\ `elif` 就是 else if 的意思<br/><br/> 試著解讀下面程式 ```python a = True b = True if (a): print("a is True!") elif(b): print("b is True") else: print("no one is True") ``` 最後會印出什麼呢?\ _a is True!_ <br/><br/> 這就是假設的用法 ------ :::success **for Loops** ::: 拉回正題,我們來看迴圈 仔細比較,下面這兩個是一樣的東西 ```python a = 0 print(a) a = a + 1 print(a) a = a + 1 print(a) a = a + 1 print(a) a = a + 1 print(a) a = a + 1 print(a) ``` ```python a = 0 print(a) for i in range(5): a = a + 1 print(a) ``` <br/><br/> `for` 就是一個這樣的累加器\ 會一行一行的跑,直到「離開了這個迴圈」再繼續往下一行邁進<br/><br/> 下面是一個計算正方形面積的程式 ```python length = int(input("enter the length: ")) #輸入邊長 answer = 0 #一開始的面積計算是0 for i in range(length): answer = answer + length #每一次都在原本的數值上加上邊長 print(answer) #印出答案 ``` 如果想要看它每一次加的過程,可以把 print 移到迴圈裡,\ 這樣每跑一次迴圈,就會印出當下的結果唷<br/><br/><br/> 現在寫一個能要求使用者輸入兩個邊長,然後用累加器計算相乘結果的程式吧!<br/><br/><br/> :::success **while Loops** ::: 如果說 `for` loop 就是跑完範圍就會結束跳往下一行,\ 那麼 `while` loop 就是永遠不會主動結束的迴圈\ 常常,我們都會卡在結束不了的迴圈裡,有時候還要強制關機呢(笑)<br/><br/> 以上面的程式為例,如果我們把 `for` loop 換成 `while` loop 就會變下面這樣: ```python length = int(input("enter the length: ")) #輸入邊長 answer = 0 #一開始的面積計算是0 while(True): answer = answer + length #每一次都在原本的數值上加上邊長 print(answer) #印出答案(永遠不會發生QQ) ``` 這時候,answer 就會一直加一直加,永不停止\ 程式一直卡在 `while` loop 裡面沒有辦法跳出來,到下面的 `print(answer)` 那邊<br/><br/> 我們把 `print` 放到迴圈裡面看看吧,這時候就可以真真實實感受到 infinite loop 的恐怖囉<br/><br/> 上面無限迴圈很明顯地,問題就出在 ```python while(True) ``` 這邊,括號內的是這個 loop 進行的條件,如果是 `True` 就會跑一次這個迴圈\ 上面放了 `True`,而 True == True,所以當然是一直跑囉<br/><br/> 所以我們來改變看看條件\ 最簡單的方式就是再加入一個計算迴圈跑幾次的 **counter**\ 試試 ```python length = int(input("enter the length: ")) #輸入邊長 answer = 0 #一開始的面積計算是0 counter = 0 #計算迴圈次數 while(counter < length): answer = answer + length #每一次都在原本的數值上加上邊長 counter = counter + 1 print(answer) #印出答案 ``` 依照上面的程式,如果輸入 10,會印出什麼呢?<br/><br/> _100_<br/><br/> 現在把之前寫過的,拿來計算長方形公式的 `for` loop 改成 `while` 吧<br/><br/><br/> :::success **break** ::: 其實要離開或說結束一個迴圈還有很多方法\ 例如我們可以在迴圈裡用 `if` 來控制\ 關鍵字 `break` 就是結束迴圈的意思\ 試試 ```python run = 0 while(True): run = run + 1 if (run > 10): break else: print("loop still running!") print("loop ended!") ``` ------ <br/> ::: success **Modules** ::: 迴圈是程式裡不可或缺的部分,它可以在讓程式簡短很多的同時完成許多其他事\ 後面會再介紹更多用法\ 現在我們的程式架構愈來愈複雜完整了,這裡再介紹一個好用的東西:\ Module 模組 白話文是:別的地方來的 code,不論是 type 或 function<br/><br/><br/> Python 有很多好用的 module 很多都是內建的,只要跟著指示就可以了\ 想要使用時,在程式開頭用 `import` 引進 \ 以下介紹兩個<br/><br/> ```python import random ``` 顧名思義,`random` 就是隨機的意思\ 引進來的 random 是一個 object(或 class 或 type :) 可以幫你產出各種隨機的東西\ 我們來用用 `random.randrange()`,[用法點我](https://docs.python.org/3/library/random.html#random.randrange) 根據既有的知識,既然 random 是一個 object、randrange() 後面有括號、兩者之間還是一個點,那麼 randrange 就是 random 旗下的 method 了 <br/><br/> 簡單來說,如果要在 range(10) 中選一個整數,就用 `random.randrange(10)` 翻成中文就是 「手上有一個被 import 進來的 random object 了」 「現在要對我的 random object 使用 randrange」 「使用 randrange 時帶入 10,這樣它就知道我的範圍了」 <br/><br/><br/><br/> :::spoiler 現在寫一個抽籤的程式吧 參考架構如下 * 一個變數(user input)代表「使用者輸入班上人數」 * 一個變數(user input)代表「使用者輸入要抽出的人數」 * 用一個 for loop 一次抽一個人,然後印出來 * 最後說抽籤結束<br/><br/> 寫出來之後想想看 1. 要怎麼讓最後一號也有被抽到的機會? 2. 萬一使用者輸入的「要抽出的人數」比「全班人數」多,怎麼辦? 3. 有辦法把 for loop 換成 while loop 嗎? ::: <br/><br/> ------ 現在來介紹另一個 ```python import time ``` [用法點我](https://docs.python.org/3/library/time.html) 常用的有 `time.sleep()`\ 可以讓程式跑得不那麼快<br/><br/> 至於取得當下時間,我偏好使用另一個 **module**,[datetime](https://docs.python.org/3/library/datetime.html#module-datetime) 不過這個比較特別,在 `import` 的時候,我們會用 ```python from datetime import datetime ``` 因為 `datetime` 本身是一個更大的 object,我們只有要用到它旗下的 datetime object 而已(可以理解成,對,它跟它旗下的 object 撞名 要叫出當下時間,可以用 `datetime.now()` 或 `datetime.today()`<br/><br/> 如果上面一開始不是寫 `from datetime import datetime`\ 而是只有 `import datetime`\ 這邊要叫出時間就要變成 ```python datetime.datetime.now() 或 datetime.datetime.today() ``` <br/><br/> 各種 module 的用法我們後面會再解釋\ 簡單來說,第一個 datetime 是一個裝了很多模組的大資料夾,第二個則是我們要的模組\ `now()` 或 `today()` 是模組裡的功能\ 我們透過 點. 來一層一層進入 <br><br> :::spoiler `References` function vs. method https://www.geeksforgeeks.org/difference-method-function-python/ ::: :::spoiler `Additional Readings` chapter8.2 https://runestone.academy/ns/books/published/thinkcspy/MoreAboutIteration/Theforlooprevisited.html chapter8.3 https://runestone.academy/ns/books/published/thinkcspy/MoreAboutIteration/ThewhileStatement.html chapter5 https://runestone.academy/ns/books/published/thinkcspy/PythonModules/toctree.html ::: <br></br> :::info [BACK](https://hackmd.io/@lhsueh1/python101) :::