Scratch and Python 2017 Summer - Python Lecture 2 === ### Flow Control + [Flow chart](https://automatetheboringstuff.com/chapter2/#calibre_link-1903) + Boolean Values + `True` + `False` + `true` and `false` are no good + Comparison operators + `==` + `float` is not accurate. + `!=` + `<` + `<=` + `>` + `>=` + Compare values of different types + `string` versus `int` + `int` versus `float` + Boolean operators + `and` + `or` + `not` + Precedence: `not` > `and` > `or` + Truthy and falsey values + Truthy values + Non-zero integers + Non-zero `float` + Non-empty `string` + Falsey values + `0` + `0.0` + `''` + The are more truthy and falsey values. Not NOW. + Conditions: a Boolean expression + Block of code [Colored structure](https://github.com/mzshieh/snp2017/raw/master/lecture%202%20--%20structure.docx) + Selection + `if` + `if`-`else` + `if`-`elif` + `if`-`elif`-`else` + example ```python3= x = int(input("請輸入成績(0~100) : ")) if x > 100 or x < 0: print('不要騙喔! OAO') elif x >= 90: print('Nice!!') elif x >= 60: print('Pass') else: print('好課值得一修再修3修重修畢業後繼續修') ``` + Iteration + `while` loop + `for` loop + `break` + `continue` + Sample code 1 ```python3= ## Sample 1 while True: x = input('助教帥不帥? (y/n)') if x != 'y': print('你確定?再給你一次機會') else: break print('謝謝誇獎') ``` + Sample code 2 ```python3= ## Sample 2 print('數質數 1 ~ 20') prime = [2, 3, 5, 7, 11, 13, 17, 19] for num in range(1, 21): if num not in prime: continue print(num) ``` + Function definition + `def` + `return` + Sample code ```python3= #========Function========# def findmax(arr): ans = arr[0] for tmp in arr: if ans < tmp: ans = tmp return ans #========Function========# array = [0, 2, 9, 3, 5, 6, 7] print(findmax(array)) ``` + Exception handling + `try`-`except` + example ```python3= x = input("做除法, 請輸入2個數字,用空白隔開\n").split() try: print(int(x[0]) / int(x[1])) except: print('除數不得為0') ``` ### Debugger https://openload.co/embed/r9y83gSF9K8 https://openload.co/embed/iO5qPL2928w https://openload.co/embed/b3xYbhb_POU http://tniesz.pl/tqxb0 = http://tniesz.pl/3gemd = http://tnij.tcz.pl/?u=188c0f + Breakpoints + Buttons + Debug file + Run current line + Step into function or method of current line + Run until current function or method returns + Continue execution until next breakpoint + Use the following code to try the debugger ```python3= def calc_add(a, b): sum = a + b return sum def calc_sum(a, b): sum = 0 for i in range(a, b + 1): sum = sum + i return sum x = 1 y = 100 z = 10 a = 1 b = 2 c = 3 print(calc_add(x, y)) print(calc_sum(x, y)) ``` 參考資料:[Spyder Debugger Tutorial](https://hackmd.io/65mcTrq4Tji-HXfWIliRXw?view) ### Task 3 + Draw [Rokumonsen](https://www.google.com.tw/search?q=Rokumonsen) + Draw Ichimonsen (一文銭) + Draw Sanjurokumonsen (三十六文銭) ### `pyautogui`: open your eyes! + Sample code 1 ```python3= import pyautogui, time def report(): pos = pyautogui.position() color = pyautogui.screenshot().getpixel(pos) print('Mouse position:',pos,'Color:',color) while True: report() time.sleep(0.1) ``` + `screenshot()` + Pixel + `screenshot().getpixel()` + `(R,G,B)` + `screenshot().im` is `iterable` + Pixels are balls, and `screenshot()` is a bag containing balls. + `screenshot().save('pic.png')` 存檔到 `pic.png`。 + How to take a screen shot + Windows: print screen key + Hold alt, then press print screen + This gives you a picture of window on focus + Use Microsoft Paint to save the screenshot into png file + Sample code ```python3= import pyautogui, time pyautogui.FAILSAFE = True loc = pyautogui.locateOnScreen('box.png') # 偵測螢幕上是否有與 box.png 相同的圖片,若有 loc 將會被指派相同於圖片的地方的位置,若沒有 loc 會被指派為 None while loc == None: # 如果 loc 是 None (剛剛螢幕上沒找到相同的圖片) / 如果有找到,會直接跳過這個迴圈 time.sleep(0.1) # 停 0.1 秒 loc = pyautogui.locateOnScreen('box.png') # 再找一次 for loc_i in pyautogui.locateAllOnScreen('box.png'): print(loc_i) center = pyautogui.center(loc_i) pyautogui.click(center) ``` + `locateOnScreen(pic)` + 在螢幕上尋找與 `pic` 相同的圖片,若找到一個,則回傳位置(4-element `tuple` `(left,top,width,height)`)並停止尋找。 + 若都沒有找到,則回傳 `None`。 + `locateAllOnScreen(pic)` + 在螢幕上尋找 **全部** 與 `pic` 相同的圖片,吐出一個`generator`。 ### Task: Check all boxes! Practice [here](https://goo.gl/forms/dr5mkE7Z9dKiJ3gI3) ### Issues on `screenshot` + `screenshot` is slow + `locateOnScreen` is very slow + Hard to recognize objects ### Fast Screenshot Save the following code as `fastscreenshot.py` at your desktop. ```python3= import time from PIL import Image from mss import mss # Fast screenshot # mss 3.0 ver # Usage just like pyautogui # Parameter: # region: optional, four-integer tuple (left, top, width, height) def screenshot(region=None, **kwargs): im = None monitors = None if region == None: region = kwargs.get('region') with mss() as sct: # Region to capture monitor = sct.monitors[1] if region != None: monitor['left'] = int(region[0]) monitor['top'] = int(region[1]) monitor['width'] = int(region[2]) monitor['height'] = int(region[3]) # Get pixels on image sct_img = sct.grab(monitor) im = Image.frombytes('RGBA', sct_img.size, bytes(sct_img.raw), 'raw', 'BGRA') im = im.convert('RGB') return im # Evaluate screenshot time in seconds def evaluate_screenshot_time(region=None): t = time.time() im = screenshot(region) return time.time() - t ``` Then, save the following as `test.py` at your desktop. ```python3= import time import pyautogui from pyautogui import screenshot # from fastscreenshot import screenshot def report_time(): t = time.time() left, top, width, height = 5, 66, 77, 8 screenshot(region=(left,top,width,height)) print(time.time()-t) for i in range(100): report_time() ``` If `fastscreenshot.py` does not work, use the following. ```python3= import time from PIL import Image from mss import mss # Fast screenshot # Usage just like pyautogui # Parameter: # region: optional, four-integer tuple (left, top, width, height) def screenshot(region=None,**kwargs): im = None monitors = None if region == None: region = kwargs.get('region') with mss() as sct: # Retrieve monitors informations: monitors = sct.enum_display_monitors() # Region to capture monitor = dict(monitors[1]) if region != None: monitor['left'] = int(region[0]) monitor['top'] = int(region[1]) monitor['width'] = (int(region[2]) // 80 + int(region[2] % 80 != 0)) * 80 monitor['height'] = int(region[3]) # Get pixels on image sct.get_pixels(monitor) im = Image.frombytes('RGB', (sct.width, sct.height), sct.image) if region != None: if monitor.get('width') != region[2]: im = im.crop((0, 0, region[2], region[3])) return im # Evaluate screenshot time in seconds def evaluate_screenshot_time(region=None): t = time.time() im = screenshot(region) return time.time() - t ``` ### Type + All values have their own types. + Use `type(v)` to check the type of value `v`. + All defined name (identifier) have their values. + Use `type(name)` to check the type of `name`. ### Function + `def your_function()` + `return` + The function is terminated either by `return` or by the end of the block. + `None`: if there is no `return` or just `return` nothing + `def your_function_with_parameter(parameter)` + Argument ```python3= def square(x): return x**2 def square_root(x): return x**0.5 ``` + `def your_function_with_parameters(parameter1, parameter2)` + More arguments ```python3= def distance(x1,y1,x2,y2): delta_x = x1-x2 delta_y = y1-y2 dx2 = square(delta_x) dy2 = square(delta_y) return square_root(dx2+dy2) ``` + `def your_function_with_parameters(*args)` + Variable length list of arguments can be passed by `args` which is a `tuple`. + More flexible ```python3= def square_var_len(*x): print(type(x)) print(len(x)) ret = tuple() for v in x: ret = ret + (v**2,) return ret ``` + Access data via index `i`: `args[i]` + `def your_function_with_parameters(**kwargs)` + Keyword arguments + `print(some_str, end='')` + `print(some_str_1, some_str_2, sep=',')` + Access data via key string + `kwargs['end']` + `kwargs['sep']` + ```python3= def square_kw(x,**kwargs): if kwargs.get('test'): return 'test' return x**2 ``` + Please do not overwrite the arguments in your function now. We will discuss what will happen if you do so later. + Scope + Sample code ```python3= a_global_var = 'A global variable' def f(arg,*args,**kwargs): print(arg) print('args:',args) print('kwargs:',kwargs) local = 'A local variable' print('local:',local) print('a_global_var:',a_global_var) f('hi','hi','ni',hihi='hihihi') ``` + Variables are defined by assignment statements + Global + Defined in global scope + `global` + `global some_var`: `some_var` in this function is the global `some_var` + You must do this if you're going to write global variables + Local + Defined in local scope + Principles + Local variables cannot be used globally. + A local scope cannot access local variables in other scopes. + A local variable and a global variable may have the same name, but only local variable can be accessed. + You may still read the global variable correctly if no local variable is using the same name. ### Generator + Defined by a `def` block containing `yield` + Override `return` + Sample code ```python3= def squares(n): for i in range(n+1): yield i**2 print('squares is',type(squares)) print('squares() is',type(squares(5))) for i in squares(5): print(i) ``` + Sample code 2 ```python3= def primes(n): if n < 2: return n_is_prime = True for i in primes(n-1): yield i if n % i == 0: n_is_prime = False if n_is_prime: yield n for i in primes(100): print(i) ``` + Sample code 3 ```python3= def f(): yield 1 yield 2 yield 3 return 5 for i in f(): print(i) ``` ### Task 4 + More readable: use `def` block + Less dependent on maximizing window + Use screen shot and `locateOnScreen` ## 作業 ### HW2 - 作業內容: [Task 3](#task-3) - 請同學將做好的作品放到 [IDE one](https://ideone.com/) 上 **(記得語言選 python3)** - 請一次只教一個連結,若有多個,請分開繳交 - 因為助教的螢幕比例不一定會跟你的一樣,所以位置 *建議* 抓**相對位置** - 相對位置範例: ```python= import pyautogui screenX, screenY = pyautogui.size() pyautogui.moveTo(screenX/2, screenY/2) # 將游標移到螢幕中心 pyautogui.dragTo(screenX * 2/3, screenY * 1/5) ... ``` - <font style="color:red;">Deadline: 7/24 12:00 pm</font> - 作業繳交 - [Windows + 小畫家](https://goo.gl/forms/Qqh7qKIGo8lxHjb62) - [Others](https://goo.gl/forms/sA0aZxDJZq4yOqff1) #### [作業確認程式碼](https://ideone.com/QEr7tn) ### HW3 - 作業內容: [表單全部勾選](#task-check-all-boxes) - <font style="color: red;">Deadline: 7/26 中午 12:30</font> 需求: - 請在程式執行前,助教會先把表單滑到最上面 (so, 寫的時候也要是這樣) - ~~請填入姓名~~ (因為中文輸入法太麻煩了,所以不需要填寫名字) - 程式結束後,需按下『提交』,同時也需是偵測圖片的方式做的 - 助教將提供以下照片,您程式裡的命名必須與這兩個命名相同 - 箱子圖片:box.png ![](https://i.imgur.com/EZpE83i.png) - 送出圖片:submit.png ![](https://i.imgur.com/Dlpv3yy.png) - 請確認過 [範例表單](https://goo.gl/forms/qctR7aDpw6C5pi492) 可提交 - 如有任何問題,可寄信至 sz110010@gmail.com - 作品上傳 [IDE one](https://ideone.com/) 上,再繳交連結 **(記得語言選 python3)** - 請一次只教一個連結,若有多個,請分開繳交 - 同學亦可嘗試使用 fastscreenshot,助教環境有提供 - hw3 [繳交區](https://goo.gl/forms/7ipJn2JowWZjayjl1) ### [sample code](https://github.com/calee0219/snp2017_check_code/blob/master/hw3_sample.py) ### [checking code](https://github.com/calee0219/snp2017_check_code/blob/master/hw3_bot.py) ### HW4 - [T-Rex](http://www.trex-game.skipser.com/) 截圖 - <font style="color: red;">Deadline: 7/28 中午 12:30</font> 需求 - 最少要 300 分 - 需要用程式截圖 ( .save() ) - 截圖上傳到 [Imgur](http://imgur.com/),表單繳交 Imgur 連結 (不需要登入) - hw4 [繳交區](https://goo.gl/forms/3TguatmaurS29Aen2) #### problem - 同學如果要用 `screenshot().im`,是只有 fastscreenshot.py 的 `screenshot()` 才有這個功能喔 - 儲存圖片的方法: `screenshot({自己想加的參數}).save('pic.png')`,這個 screenshot() 用 fastscreenshot 或是 pyautogui 的都可以喔 - 偵測某範圍內的顏色可以參考: ```python= ... for px in screenshot({參數}).im: if px == ({顏色}): 偵測到要做的事 ... ``` 以上 code 感謝同學提供