[新手Python 應用搭建指南] 2. if/ for /while / function /class
本系列文章我將手把手的帶你們完成應用程式專案。從選題,找資料,探索資料,最後進而搭建出應用並且部署在網頁上讓你可以秀給你的媽媽,老闆或是阿娜答。
關聯文章目錄
4篇轉職工具箱 Four weeks to reach even better
4篇新手Python 應用搭建指南
- python 基礎資料結構
- (本篇)python if/ for /while
- python套件 pandas/ 專案老電影選擇器
- python專案 食譜選擇器
上一周我推薦了我最喜歡的線上課程資源,不論你是喜歡中文上課還是順道練習英文文件閱讀能力的各式課程都有介紹。相信對程式一樣滿滿熱情的你應該已經至少順刷過任何一門自己喜歡的課程了吧。
好吧2/3的人應該露出了不失禮貌的微笑。向下圖這樣。
沒關係,可以理解學程式語言就像上健身房一樣,我辦張卡肌肉就會長出來了不需要練的。類比程式就是:
太好了,乾貨哥發文,我加個書籤就會自己長知識了,不用自己練習的。
我必須很坦白地跟你說,所有學習的過程都是需要自己一步一腳印的,任何看起來順風順水的人都有它在紮馬步的時候,只是你們沒看見而已,共勉~
今天的一大重點就是對程式麻瓜很抽象的迴圈,希望你們再今天看完這篇文章時不是把腸子絞著,而是帶著上面這張笑臉離開。
我無比渴望馬上開始跟你們講解應用搭建有多簡單,我們只要十分鐘的copy paste就可以讓東西動起來,然而你不會只想當copy paste小魔人而已,如果是的話,其實你可以直接打開任何一個應用套件的教學文件,一步步step by step 輕鬆寫意。
我期許你們有自己照自己想法更改的能力,也因此我今天就再陪你們紮一點馬步,講講程式中最重要的可遷移能力,控制流程(if),迴圈(for / while), 抽象封裝(function/ class),不論你使用任何一種高階程式語言,不可避免的一定會碰到上面說的這些內容,如果沒有,那我也不知道那些程式在寫什麼了… 所以今天的第二課十分重要,可以讓你們不管學會任何語言都避免不了的,aka程式的陽光空氣水的基礎組件。
控制流程(if)
我們來建構一個最簡單的例子,下雨天要帶傘,我們讓程式幫我們控制
我們先檢查氣象預報,看會不會下雨,接下來再決定要不要帶傘,為了方便展示,我們就簡單寫一個rainy_day = True,if rainy_day,這個判斷式等校於if rainy_day == True, 也等效於 if rainy_day == True
再進行bool(True/ False)判斷時這裡建議使用is ,更為精確,是因為python有指定一個固定的記憶體地址來儲存bool這些值,如果是要進行其他數值或是其他資料型態的比較,就不建議這樣做了。
觀察上圖,你可以注意到,if 後面其實就是判斷後面的bool有沒有成立,當你對某個變數進行比大小等行為時,就可以拿到一個 True 或是False,比如下圖你可以判斷溫度能不能住人,用36度來當衡量基準,我們可以看見右方數值跟衡量基準比較時,其實也是在回傳 True 或 False
而 if 右邊如果放了一個True 下方縮排的部分就會執行,像上面的例子,因為28.4沒有大於36,所以就變成else被執行了, 回傳了還行
我們再來看另外的例子吧,如果爸媽在家就不用帶鑰匙,反之不在的話,就要提醒我帶鑰匙
以及這個手機電夠不夠,判斷要不要帶行動電源
也能判斷需不需要領個錢,注意我使用了if not,我已我檢查的是反向的邏輯,如果錢不夠,出門就要領點錢
以上這些就是我出門檢查的流程,既然是流程,我們就可以把這一系列的檢查塞進函式裡面
函式的定義在最前面要放個def,空格後黃色字的區塊是接函式的名字,接著後面用逗點隔開要定義的變數名稱,然後下方整個區塊要記得縮排
注意變數在這裡只是拿剛剛的命名來復用,其實只要函式內文定義如同變數區域定義的即可,所以如果你看的懂你也可以全部寫abcd,但你大概半小時後就忘了自己為什麼要這樣定義了,函式的變數請小心命名,不用擔心打太長,可以節省將來自己或同事的閱讀時間,多打幾個字不要多少時間的。
函式定義完成之後,我們就可以簡單的呼叫其來使用了
之後每次要出門前就只要敲一下,清單就會跟你說該怎麼做了,很方便吧,下方提供兩種函式的使用方式,第一種是位置型的指定方式,一個蘿蔔一個坑,就指定好變數就行,另一種則是對每一個參數都指名道姓的填入值,像下方的範例那樣,通常建議使用下面那種,因為有較佳的可讀性。
迴圈(for / while)
接下來就來講講之前提過的for in loop
for in loop大概是python最讓人喜歡的功能之一,我們可以看看下方實現一模一樣功能的函式,用了多少篇幅來描述,for in 幫你用最直覺的方式,把該做的事情做完,但是下面這種用法還是要了解一下,為什麼呢,因為大部分的語言的迴圈邏輯是像下面這樣,所以如果要有流暢面對大部分語言的話,就來了解一下for 迴圈一般是怎麼工作的吧~
python 只要是可迭代物件(iterable)比如list, dict等等,都可以使用for in 迴圈來獲取裡面的每一個元素,list 會被遍歷逐一取出,而dict 在使用for in 時會回傳一個個的key。
至於要如何取得value呢,有兩種方式,第一種就是先找到key,在用key去找值,第二種則是讓dict直接傳item(包含key, value出來),你再將其賦值到2個變數後使用。
下方可以看到一個實務一點的例子,可以看到我們一次性的把所有人名當key,並把薪水當value ,最後整合到字串中印出
內建函式: 剛剛上面出現了 range() 與 len() ,應該很多人好奇如何使用
range 也是一個可迭代物件,傳入一個int,回傳一個可迭代的range 物件,如果for in 作用於一個range物件,可以逐一取出從0開始的n個數字,很適合拿來當for迴圈計數器使用
len 是python一個用來量測長度的內建方法,可以對dict量測其key總數,string 可以量測其字元數量,對list則量測其元素數量。
While迴圈
接下來來介紹一下while迴圈的使用,通常while迴圈使用在可以讓使用者重試無限次的應用情境,但我們先將問題簡化,舉個有趣點的例子。
題目是這樣: 現在到了晚餐時間,你想問問女朋友有沒有想吃的東西,但有可能是你已經惹她生氣了,你講甚麼她都說不要。你心中猜大概三次沒有問出答案,應該就GG,要趕快先道歉要緊。 廢話不多說,上程式碼
上面展示,問了三次都還沒有得到答案的樣子,下面則是使用者輸入到第二次就得到理想答案並break 出去的使用情境。
注意,python有兩個流程控制用的字眼,分別是 break與continue
兩個分別使用情境不太一樣,break用於結束整個迴圈(一層),並跳出
continue只跳出本次迴圈,並進入下一次迴圈
但以上面的例子來說,你會發現,用for可以解決,for 可以解決的事情我們通常不會使用while,for是一個很明確,很封閉的解決方案,while是一個開放自由的寫法,但是因為他過於開放,所以你可能會引入另一個問題無窮迴圈,就是迴圈一直跑跑到電腦停不下來的情況,有時候電腦還會風扇起飛。然而使用更理想,範圍定義清楚的for迴圈會更理想一些。
那什麼情境,用while可以接受呢。其一是多執行緒,要引入變數控制執行緒執行,好吧我承認這太高深,這我們之後有機會再討論。另一個則是一開始講到的讓使用者無限次輸入,給我打到對為止的情況
如果使用for迴圈就會很難定義上面這題該怎麼做,但for迴圈可以限定使用者打3次或5次,如果幾次以後才沒辦法打對,就中斷程式,for迴圈的同題目改寫下方展示,我定義了最大重試次數,並且讓使用者輸入,輸錯的話,就會繼續下一個迴圈(retry_time這個 counter會自動+1)當達到最大的次數的時候,就會引發 max retry error。如此一來,就是提供類似功能,但是避免使用較不受控制的while loop。
今天的內容一樣先付上colab連結,歡迎大家clone回家多多練習
抽象封裝(function/ class)
想想我們今天有一系列的動作要完成時,我們會怎麼溝通.
你走進一家早餐店,請老闆幫你煎個蛋餅外帶,還是會請老闆幫你煎一張蛋餅皮,三分鐘之後翻面並在另一區打一個蛋,並在一分鐘後將翻面的蛋餅皮蓋到你的蛋上淋上醬油膏.
你應該會說蛋餅外帶吧
換成程式碼應該會像下面這樣,你可以有一個抽象的名字去代稱一系列的動作,就會讓你可以省掉很多重複的工作,如果你跟老闆討論你的蛋餅的製作細節,老闆應該也會覺得你很奇怪,為什麼要講那麼多
現在你可以隨時隨地都呼叫你這個“煎個蛋餅吧”程式,它都會很穩定的給你一樣的結果. 這樣也可以避免你在copy paste一整段程式碼的時候有出錯的可能性.
另一個function重要的特性為,可以定義參數,如果你每天都可能要買好幾份蛋餅,你可能會希望可以一次叫好幾份蛋餅,而不是老闆給你一份才點下一份吧,這時候我們可以拓展我們剛剛的煎蛋餅程式,變成煎好幾份蛋餅
這裡我們多一個變數輸入qty ,可以讓使用者定義所需要的份數,同時我們還貼心的定義默認值(qty=1),就是當使用者沒有講自己要幾份時,我們預設他應該只要一份。
而當使用者輸入他要十份時,就會回傳做好十份的步驟了
接下來老闆發現只賣清蛋餅的生意比較差,想要拓展不同的口味,因此我們也修改了我們的方法,容許使用者輸入口味,現在你可以指定額外的配料,老闆在煮的時候就會記得一起加熱
同樣的道理,我們也可以把同樣的邏輯應用在點飲料上面,你可以創造一個點飲料的答覆機器人,他會根據使用者的輸入來回答他的飲料,或是默認珍奶正常正常。
function的好用之處就是可以將醜陋的內部實現隱藏其來,並且可以提供一些默認值,cleancode中有一個DRY原則(don’t repeat yourself)就表明了一直重複的複製貼上類似的程式碼是一種壞氣味,是我們需要避免的事情。透過程式,將相同的部分封裝,就能讓開發者更好維護,可讀性提高,同時不會因為改了一處而忘記改另外一處而導致系統沒有按照想像中的邏輯運作。
class則是把相同的理念更近一步提升,透過將同類型的function封裝再一起,讓一個class有相同的職責
class對新手來說可能比較抽象,完全是可以接受的,你可以慢慢透過使用去理解。對新手來說只需要知道什麼是內部的參數,什麼是內部的方法,以及他們是怎麼呼叫的這樣就可以了。至於什麼物件導向就要先學繼承的,你還是送新手一個刀子比較快
現在我們來介紹早餐店最勤勞的員工小美,她的專長是做蛋餅。
class 定義的方式由關鍵字class 後面連接的一個大寫開頭連接的字(非必要,只是一個好習慣, 比如class MyClass:)
接下來我們用def 去定義在實例化一個class的時候需要輸入的變數(__init__),實例化可以理解為建造,當我們有一個class定義的時候,我們只是擁有一張藍圖,必須要將其喚醒,比如下面的mei就是喚醒後的Worker,被喚醒的class實例我們將之稱作object(名稱通常都是小寫用底線連接)。
在這個例子中Worker實例化時需要輸入名字與職責。我們輸入了小美與做蛋餅,這樣在__init__階段就會把這些值賦予到mei這個object中,這時候你會發現一個很奇妙的字,self,究竟什麼是self,在這裡你可以理解為mei這個物件本身,所以我們把mei的name定為我們輸入的“小美”,並把美的job定義成我們輸入的“做蛋餅”
實例化完之後,如果我們需要在外部呼叫這些特性(property),就用物件名.特性名就行。如上圖我們使用mei.name, mei.job來進行呼叫
至於在內部如果要進行呼叫,我們則需要使用self, 對於這個object來說,看到自己的方式,就是透過self
如下圖,我們的我是小美,我會做蛋餅便是在內部透過self進行呼叫的
最後我們來展示一下真正的class可能會看起來的樣子
我們定義的true false回傳可以用來當pipeline的中斷點,我們pipeline要繼續進行的前提就是前置作業必須要成功地被執行,我們把每一個步驟分拆出去,成為獨立的方法(method),而呼叫method的方式也正如我們上方呼叫property一樣,都是外人call的時候 mei.method,自己object裡面call的時候則使用self.method。如此一來我們的mei就變成專職做蛋餅的一個物件啦
常常我們會import一個套件,然後就開始用 物件.method的方法去呼叫,當還沒有物件的觀念的時候可能會比較矇不知道這在幹嘛,了解物件之後就會明白,這是別人定義好的物件其下轄的方法。願大家多練習,多看code,也歡迎去找我之前在第一篇推薦過的課程,來擁有完整的物件導向設計觀念。
下週就會開始講套件與steamlit使用啦,我們就可以開始建構第一個app了
這篇乾貨滿滿的內容下,是我孜孜不倦的努力,儘管已經有草稿的情況下其實也打了5+小時,另外感謝各路好友們的校稿,讓我在光速打字的同時能夠有良好的文章品質,再次謝謝你們。
如果你喜歡這篇文章,可以按下方的手掌幫我拍手,最多可以拍五十下,另外你也可以追蹤我,這樣就不會漏掉我最新的發文~~