Scratch and Python 2018 Spring - Python Lecture 1 === ### 電腦是如何計算的? - 電腦可以 - 儲存資料。 - 讀取資料。 - 對資料進行運算,產生新資料。 - 程式運做過程 - 程式作為一種資料存在儲存裝置(storage)裡,如硬碟。 - 將程式從儲存裝置搬到記憶體(memory) - CPU 將記憶體中的指令解碼,視需求從記憶體或其他裝置取得資料存放到暫存器(register),或進行計算。 - 算完後再視情況將計算的結果存回記憶體 memory 或是其他裝置。 ### 電腦儲存資料的單位 - bit: 0/1,開/關 (通常用 小b 表示) - byte: 8 bits => 可以存 $2^8 = 256$ 個數字 (通常用 大B 表示) - 1 KB = 1024 B - 1 MB = 1024 KB - 1 GB = 1024 MB - 1 TB = 1024 GB ### 整數(int)的儲存 - 電腦只儲存 010101... 的值,0 為 通電,1 為斷電 (or 相反) - 因為基本單位是 0 跟 1,常採用二進位制表示數字 - $1_{10} = 1_2$, $2_{10} = 10_2$, $3_{10} = 11_2$, ... - 當我要存兩個數字 1 跟 2 時,如何不被搞混成 12 呢? - 固定數字儲存長度,假設為 4 bits (每台電腦都不一樣) - 1 存成 0001, 2 存為 0010 => 放在一起時是 00010010 也不會搞混成 12 了 - 這種作法能表示的數字有限 - 如何表示整數的的正負呢? - 常用的有 二的補數法(2's complement) 與 超額表示法(Excess Notation) - 二的補數法 - 我們只要把最前面的正負號改成 0 與 1 就好啦 - 因為剛剛已經定義了 0001 是 1,為了不改變這樣的定義,我們就將 0 當作正,1 當作負 - 所以 1001 就是 -1 囉~ - 那 1000 = -0 = 0 = 0000,這樣設定好像不太好,會浪費掉一個原來可以儲存的數字 - 定義負數是是將原來的數字作 0/1 互換(一補數),再加一 - ex. 3 = 0011 => -3 = 1100 + 1 (1100 是 0011 的 0/1 互換) - 這樣一來,我們可以先用 sign bit 確認出是正 or 負,在決定要如何解讀這個數子 - 這樣的運算方式在做加減時,也會神奇的成立,完全不用另外處理,大家可以試試看喔~ ### 浮點數(float) - IEEE-754 - 剛剛有講到電腦是用 0101 儲存資料的,所以 10 進位的資料都要改成 2 進位 - 如何用 2 進位表示小數呢? - $0.5_{10} = \frac{5}{10} = \frac{1}{2} = \frac{1}{10_2} = 0.1_2$ - 事實上,我們是用除法去處理,每次除 2,將商數放下,餘數拿去繼續除 - 可是用同樣的算法算 0.3 時...,不能約分成跟 2 有關的數字了!! - 0.3 不能被二進位制完整表達 => 浮點數不精確性 - 簡單介紹儲存方法 - 32 bits 為例 - 第一位是 sign bit - 接下來 8bits 是 exponent,是小數點的移動距離,二補述法與超額表示法都可 - 剩下 23bits 是 fraction,是真正的數值部分,其中因為是沿用科學記號(數字部分必定是 $01_2~10_2$ 之間),因此會把最前面 1.xxx 的 1 影藏掉 - 因此,下圖的數字應該是 $1.01_2 * 10_2^{-3} = 1.25_{10} * 2_{10}^{-3}$ (這裡的 exp 是用超額表示) - ![](https://upload.wikimedia.org/wikipedia/commons/d/d2/Float_example.svg) ### 文字表示 - 電腦存 0 與 1,要使用一些對照表,讓數字代表文字。 - 像是 97 代表 'a',98 代表 'b'... - 要存文章,就需要更多的定義,比如一些特殊的符號,像是換行等等。 - 要儲存更複雜的資料,就需要先定義格式,該如何解讀一串0與1。 ### 語言的基本構成 - 以英文為例 - 單字由一些字母構成 - 句子由合乎**語法**的一些單字構成 - Syntax (語法) - 語言的規則 - 以英文為例: I meat eat 不合語法,主詞受詞動詞並不是英文語法,主詞動詞受詞才正確。 - 以算術為例: `3 5 +` 不合語法,不是一個能夠計算的算式。 - Semantics (語意) - My car eats burger 語意不合理 (不合邏輯),車子不會吃漢堡。 - 語意解析 - 自然語言同一句話可能可以解釋成多種意思 - 我養的豬很好吃。 - 程式語言中,一個句子通常只會解釋成一種意思 - 只是這句話的意思不一定是工程師要的 - 如果不只一種可能性,稱作「Undefined behavior」,電腦會怎樣做,寫的人無法確定。 ### 錯誤 - syntactic errors - 簡單好抓,因為語法錯,電腦看不懂就不給執行啊。 - static semantic errors - 有些語言也會跳錯,因為不確定你要做什麼,電腦也可能不想幹。 - 可能造成非預測行為,因為你都不確定要做什麼,電腦就隨便做。 - 與程式設計師想要得不一樣的結果 QQ - 程式終止 - 無窮迴圈 - 錯誤答案 ## Python Programs - program (程式) 是一系列的定義與指令 - command (statements) 指揮 Python 直譯器 ### Objects (物件) and Values (值) - 所有資料都是物件 - 所有物件都有 type (型別),python 會根據型別,知道你可以對這個物件做哪些事情 - ex. 數字,是可以被家的 - ex. 人,可以走路 - 兩類 objects - scalar - 最基本的物件 - 不可再被細分 - ex. 數字 5 - non-scalar - 有一些內部的結構可再被利用 - ex. list [1, 2, 3] - scalar object 有 + `int` Integers: `1`,`0`,`-2` + `float` Decimals: `1.23`, `456.7` + Numbers in scientific notation: `1.234e5`, `-6.78e-2` + `str` Strings: `'abc'`, `"ABC"`, `'"'`,`"'"` - 可以用 type() 來看型別 - 型別轉換 - float(3): 將 整數 3 轉為 浮點數 3.0 - int(3.9): 將 浮點數 3.9 轉為 整數 3 - non-scalar object 有 + `tuple` 序列 + `tpl = (3,5)` + `list` 清單 + `lst = [1,2,3,4]` + `lst[1] = 9` + `dict` 字典 + `dct = {}` + `dct = {1:2}` + `dct['name'] = 'MZ'` ### Expressions (運)算式 - 將 objects 跟 operators 連接形成 expressions - expression 必定有 value - 簡單 expression 的 syntax - {object} - ({expression}) - {expression} {operator} {expression} | 運算子 | 意思 | 用法 | 輸出型態 | | :-: | :-: | :-: | :-: | | + | 加 | i + j | 若 i or j 中有任一是浮點數,則為浮點數,若無,則為整數 | | - | 減 | i - j | 同上 | | * | 乘 | i * j | 同上 | | / | 除 | i / j | 浮點數 | | // | 整數除 | i // j | 整數 | | % | 餘數 | i % j | 整數 | | ** | 次方 | i ** j | 浮點數 | - 運算優先序 - () 最優先 - `** > {*,/} > {+,-}` - 同等級左邊優先:`+`,`-`,`*`,`/` - 同等級右邊優先:`**` ### 綁定 變數 (variable) 與 值 (value) ![](https://i.imgur.com/CtDegDk.png =250x) - 用 等號(=) 綁定(binding) - 值會被存進 memory - 為何要使用變數 - 可以重複使用 - 輕鬆改變值 - 可讀性較高 - 重新綁定 - 同一個變數可以改變綁定的值 ```python3= a = 10 print(a) # 10 a = 20 print(a) # 20 ``` ### `pyautogui` + 用程式控制鍵盤和滑鼠 + 你可以用程式操作鍵盤輸入以及滑鼠的點擊,將可以取代很多人工操作。 + 避免裝備不夠靈敏、感應延遲等問題。 + <del>使用範例:在《蟒蛇谷》遊戲裡,若玩家想要獲得PillowDrawer特殊道具,則必須點擊主城的Tree一千下,每點擊一千下後有一定機率獲得。在學習了pyautogui之後,我們就可以以對滑鼠較友善的方式獲得這個道具。</del> + `import pyautogui` + 控制滑鼠 + 取得螢幕大小資訊 + `width, height = pyautogui.size()` + 取得鼠標位置資訊 + `x, y = pyautogui.position()` + 螢幕的座標方式 + 左上方: (0,0) + 右下方: `pyautogui.size()` + 移動鼠標到指定位置 + 絕對位置: `pyautogui.moveTo(x, y, duration)` + 你目前可以忽略 `duration` 這個參數。僅輸入 `pyautogui.moveTo(x, y)`,鼠標將移動至`(x, y)`的位置。 + 相對位置: `pyautogui.moveRel(x, y, duration)` + 若當前座標為`(a, b)`,輸入上方指令後鼠標將移動到`(a+x, b+y)`位置 + 點擊滑鼠 + `pyautogui.click(x, y)` + 左鍵點擊`(x, y)`處 + `pyautogui.rightClick(x, y)` + 右鍵點擊`(x, y)`處 + `pyautogui.doubleClick(x, y)` + 左鍵雙擊`(x, y)`處 + 拖曳(指得是長按的動作) + 絕對位置: `pyautogui.dragTo(x, y, duration)` + 由當前位置拖曳鼠標至`(x, y)` + 相對位置: `pyautogui.dragRel(x, y, duration)` + 若當前位置為`(a, b)`,由此處拖曳鼠標至`(a+x, b+y)` + 滑鼠滾輪 + `pyautogui.scroll(y)` + `y`若為正值,代表向上滾動`y`單位;負值則是向下滾動。 + 控制鍵盤 + 輸入文字串 + `pyautogui.typewrite(text,delay)` + 按下特定按鍵 + `pyautogui.press(key)` + `pyautogui.keyDown(key)` + 按下某個鍵 + `pyautogui.keyUp(key)` + 鬆開某個鍵 + `keyDown`與`keyUp`組合即為`press` + [Key table](https://automatetheboringstuff.com/chapter18/#calibre_link-36) + 快捷鍵輸入 + `pyautogui.hotkey(key1, key2, ..., keys)` + Example: `pyautogui.hotkey('ctrl', 'c')` + 範例 + Windows + 從目錄頁叫出命令提示自元,印出`Hello World!` ```python= import pyautogui pyautogui.PAUSE = 0.1 pyautogui.hotkey('win') pyautogui.typewrite('cmd') pyautogui.press('enter') pyautogui.typewrite('echo Hello World!',0) pyautogui.press('enter') ``` + 其他 + `pyautogui.PAUSE = t` + 代表每個`pyautogui`的指令間間隔`t`秒 + 因為`pyautogui`的指令執行很快,可能在電腦畫面還沒有反應之前就執行到下一個指令,因此適當的延遲才能順利執行。 + 作業一: + 寫一個程式,完成下列指令: + 開啟瀏覽器。 + 開啟交大首頁:http:/www.nctu.edu.tw/ + 作業二: + 寫一個程式,開啟 [GeoGebra Classic](https://www.geogebra.org/classic) 網站,用「手寫筆」功能畫出一個三角形。 + 作業三: + 寫一個程式,開啟 [GeoGebra Classic](https://www.geogebra.org/classic) 網站,畫出一棵樹。