1. 程式人生 > >從零開始學習PYTHON3講義(三)寫第一個程序

從零開始學習PYTHON3講義(三)寫第一個程序

最有 當前 記憶 參考資料 函數調用 情況 分鐘 頁面 容易

技術分享圖片

《從零開始PYTHON3》第三講

本頁面使用了公式插件,因博客主機過濾無法顯示的表示抱歉,並建議至個人主頁查看原文。

? 我見過很多初學者,提到編程都有一種恐懼感,起源是感覺編程太難了。其實,難的也不過是開頭第一步,所以中國有古話說,萬事開頭難。

? 一個人想得到別人的幫助,通常是同別人溝通,請求對方伸出援手。溝通的工具當然是語言,甚至可能還要加上曉之以理、動之以情的表情、手勢。比較而言,請計算機幫忙就簡單多了,只需要語言就夠了。

? 人類溝通的語言,需要兩個人都能聽懂,比如碰到一個不會中文的美國人,你只能用英語跟他交流。計算機語言也是這樣,需要人和計算機都能看懂,Python就屬於人跟計算機都能懂的語言,當然這樣的語言還有很多種,幾乎已經超過了人類之間溝通的語言總和。

? 能來學Python,你對語言肯定不陌生。甭管是英文還是中文,還是計算機語言,單詞、語法都是基本的組成部分。比較大的差異在於人與人的溝通主要靠說和聽,email、發短信只是輔助手段。而即便有了人工智能的幫助,計算機仍然還是以“閱讀”你寫給它的“email”為主,來完成對你要求的理解。這裏的“email”,其實就是我們前面看到過的“程序”,沒錯,一樣是全篇的文字,而在我們的課程這裏,就是Python語言。當然啦,“email”只是形象化的比喻,你可別真的給電腦發封email。

? 此外,人工智能是我們重要的工具,但抱著“人工智能取代程序”的觀點是不對的,以目前的發展速度來看,人工智能在很多方面,包括編程方面,都可以成為我們的好助手,但遠遠還無法取代人的編程能力,這一點,你自己學過編程了就理解了。

? 為了加深印象,讓我們來看一個摘要的《XX航空公司起飛準備程序》:

  • 提前起飛時間2小時飛行機組在公司開準備會
    • 拿飛行資料、飛行計劃、天氣、通告
    • 閱讀核對以上資料,討論一下最近行業內出的事故
    • 半個小時後坐車去機場。
  • 飛機檢查
    • 機長穿著反光背心下飛機做機外檢查(看飛機的外表有無異常)
    • 副駕駛檢查駕駛艙基本設備(氧氣、逃生斧、逃生繩等)
    • 飛行管理計算機內輸入飛行計劃
    • 機長做完機外檢查後核對副駕駛輸入的飛行計劃
    • 副駕駛再次進行機外檢查
  • 旅客登機中及之後
    • 機長和副駕口頭敘述飛行計劃以及起飛滑跑和起飛後的緊急情況處置預案
    • 副駕向塔臺申請放行許可,依據放行許可修改一下飛行計劃
    • 飛機推出,機長起動發動機,啟動完申請滑行
    • 按照塔臺給的滑行路線滑行到跑道外等待進跑到許可
    • 進跑到後等待起飛許可

? 請看,這就是寫給“人”來執行的一個程序。從本質上講,這同讓“計算機”來執行的程序,並沒有什麽不同。

? 但是因為計算機尚不具備與人類相當的智能,為了避免出現歧義,方便計算機理解和處理,類似Python這樣的計算機語言額外的附加了一些特征:

  • 嚴格的語法
  • 特定的書寫格式(其實是語法的一部分)
  • 特定的單詞(或者說不允許隨意換成別的同義詞)

? 同樣是文字,寫給計算機看的文字(程序)還有這樣一些特點:

  • 必須使用半角英文字符
  • 包括:保留字(也稱關鍵字),比如運算符就是保留字的一種,保留字指的是你不能再把這樣的字符、單詞用於自定義的其它用途,比如變量名,比如函數名。Python包含大概不超過50個保留字
  • 包括:函數,有預定義標準函數、官方函數庫、第三方函數庫,這三者的區別以後我們會講
  • 包括:變量,Python有一些預定義的變量

? Python語言學習的主要內容是語法和保留字,這部分的數量非常有限。函數的數量特別是第三方提供的函數非常多,可以在使用中逐漸記憶。不常用的還可以一邊查看文檔一邊使用。

? 此外一個重點是算法的學習,學習算法能夠強化邏輯思維和抽象思維,從而促進數學和其它學科的學習。


第一個程序

? 我們已經知道了,程序就是文本,就像我們平常寫的email。所以理論上編寫Python程序,我們用任何一個文本編輯的工具都是可以的。但實際上不同的語言,都有不同的流行工具更適合使用。你可以相像一下,同樣是文字為主,Word / PowerPoint / Excel都針對了不同的應用場景。也可能有人經歷過,某款軟件用起來很方便,但適合處理英文,在中文環境使用就“水土不服”。

? Python語言也有很多流行的編程工具,我們這裏使用隨著語言本身附帶的IDLE工具。IDLE是英文Integrated Development and Learning Environment的縮寫,中文意思是:集成開發和學習環境。

? 上節課我們已經用IDLE嘗試過了Python的交互模式。在交互模式的時候,從File菜單選擇New File,會新打開一個窗口。前面說過了,這就是編程模式。
技術分享圖片
在這個新打開的窗口中,輸入下面這一行命令,如果你看的是電子版文檔,直接拷貝、黏貼也是可以的:

print(12345678+87654321)

? 之後看起來,應當是類似於下圖的樣子:
技術分享圖片
接下來從File菜單選擇Save,把這個程序存盤。需要為程序起一個在當前目錄唯一的名字,比如叫hello,或者叫first,隨你高興。存盤文件自動會有.py後綴,表示這個文件是Python的程序文件,請不要修改這個後綴,這時候完整的名字會叫hello.py。保存到什麽目錄無所謂,但是請你記住程序的位置,當然還要記住文件名。Python是允許程序文件使用中文名的,但考慮到擴展名必須使用英文,並且還有很多交流上的不方便和兼容問題,這裏建議你堅持使用有意義的英文或者拼音文件名。

? 套用董卿一句話說:見證奇跡的時刻到了!請按下F5,執行這個程序。(忘記執行程序的,出門左拐,去看看第一課講義最後部分。)
按下F5之後,當前程序的編輯窗口會退到後面,交互模式的窗口會出現在前面,並顯示運行的結果:
技術分享圖片
99999999就是12345678+87654321的計算結果,並通過print()函數打印出來。

print這個詞在英文中是“打印”的意思,我在課程的講解中也習慣上說“打印出來”,但實際上結果不明明白白的顯示在屏幕上嗎?
原因其實很簡單,最早的計算機其實是沒有顯示器的,輸出的結果,就是在打印機上。為了兼容原有的經驗、程序和習慣,print命令在很多語言中都延用至今,而且看起來,還會延用下去。


第二個程序

? 你可能註意到了,在這個課程中,很多內容都一再的重復。其實這就是Python的學習模式,不斷的重復,不斷的動手練習,書上的知識,才能變成你自己的知識。否則以Python語言30多個單詞+10多個符號的保留字,你們用兩天時間全部背過應當無論如何不成問題,但依然不會編程。
這裏我們再次引用上一節的應用題:

甲、乙兩人相距36千米,相向而行,如果甲比乙先走2小時,那麽他們在乙出發2.5小時後相遇;如果乙比甲先走2小時,那麽他們在甲出發3小時後相遇,甲、乙兩人每小時各走多少千米?(假設甲乙的速度均勻穩定)

? 解題思路上一講最後練習答案部分已經有了,這裏就不再占篇幅。我們還是從File->New File新建一個程序文件開始,在打開的新編輯窗口中,把下面的代碼拷貝進去:

y=(12*4.5-36)/(4.5*5/3-2.5)
x=(36-5*y)/3

print(x,y)

? 存盤後,再次按F5執行,如果程序輸入沒有出錯的話,會得到這樣的結果:

6.0 3.6

? 這是我們的第二個程序,我們已經可以做一個小的總結:

  • 對於簡單的計算程序來講,把在交互模式所使用的命令匯總在一起,寫到一個文本文件中,就成形成一個簡單的程序。
  • 交互模式的過程,穿插著大量思考、試錯的過程,很難有條理的保存、重用。用程序的方式,可以把交互模式實驗過程中犯錯的部分去除掉,只保留最有用的部分,而且還可以將來再次使用。

? 到了這裏,你應當再嘗試一些其它的數學計算,首先在交互模式驗證你的思想。最後把最優的方法保存到程序中,嘗試編程模式的優點,也熟悉使用你手上的編程工具。


自定義函數

? 現在假設我們把前面應用題的內容小小的修改一點,從“甲乙兩人相距36千米”改成“甲乙兩人相距48千米”,這裏只是為了舉例,請忽略現實中些微的不合理因素。

甲、乙兩人相距48千米,相向而行,如果甲比乙先走2小時,那麽他們在乙出發2.5小時後相遇;如果乙比甲先走2小時,那麽他們在甲出發3小時後相遇,甲、乙兩人每小時各走多少千米?(假設甲乙的速度均勻穩定)

? 既然上面我們已經試驗並保存過了編寫好的程序,打開重新編輯一下,就能用於這一道題的求解了。如果剛才的程序窗口已經關閉了,從File菜單點Open,選擇自己保存的文件,這部分在第一講介紹過了。
為了讓你看的清楚,我完整的粘貼一遍修改後的程序:

y=(12*4.5-48)/(4.5*5/3-2.5)
x=(48-5*y)/3

print(x,y)

? 存盤後,F5執行程序,結果是:

14.0 1.2

? 甲肯定騎了小黃車,而乙需要拄拐杖是沒跑了:)
現在你應當再次感受到了使用程序方式的優勢。其實這種方便還能更明顯,下面我們來嘗試用自定義函數的方式來解決。

? 上一節我們已經了解,程序中函數的概念,同樣來自數學:$$
y = f(x)
$$
? 在數學函數中,y表示函數計算的結果,f()代表一個函數,x則是函數的參數。上例中我們使用的Python內置的標準函數print(),x/y是print的參數,我們要的是顯示結果,返回值我們不關心,丟棄了(是的,Python中的函數,是可以沒有返回值或者忽略返回值的)。

? 下面用一個簡單的例子來展示自定義函數,這裏我們定義一個數學中的線性函數:

def line(x):
    y=3*x+4
    return y

print(line(5))
  • def和return是Python的保留字,實際還有冒號“:”也算是保留字的一種

  • line是函數名,x是傳遞到這個函數的參數

  • def line(x):這樣的形式,包括def和line之間的空格,就是自定義函數的語法

  • y=3*x+4是一條賦值語句,昨天的課程你肯定還記得,把算式3*x+4的結果賦值給變量y。在計算機中,這樣的算式也稱為“表達式”

  • return y是把y的值,當做函數的返回值返回給函數的調用者,同時這條語句結束函數的執行,返回函數被調用的位置

  • return是保留字,所以後面不用小括號“()”把y包裹起來;與此對應的,函數調用則必須有小括號把參數包裹起來。

  • print(line(5))這一行,是連續的兩個函數調用。讀的時候先從最內一層讀起。首先是使用參數5調用我們自己定義的line函數。隨後把line函數計算的結果返回給print函數顯示出來。這一行類似這樣的形式:

    tmp=line(5)
    print(tmp)
  • 函數定義跟下面函數調用之間的空行,也就是上面的第4行,並不是必須的,但這樣寫可以讓你的程序看上去結構更清楚

  • 函數定義def那一行之後的兩句命令,前面的固定長度空格,叫做“縮格”,表示這兩句從屬於函數定義,是必須的。這部分也稱為“函數體”

  • 從語法規定上說,縮格使用任意多個空格或者TAB制表鍵,都是可以的。但整個程序文件,所有的縮格必須使用完全相同的格式。比如程序中出現的第一個縮格是是使用了1個TAB鍵,那整個文件所有的縮格必須都是使用1個TAB鍵。這是特別需要註意的,很多初學者都會在這裏犯錯

  • 官方文檔建議縮格統一使用4個空格鍵,因為這樣最美觀,並且比TAB鍵有更好的兼容性。

  • 縮格可以嵌套,表示多重的層級關系。程序中最高層級的語句,必須頂格書寫,前面不能有空格或者制表符

  • 最後也是最重要的,執行順序上,每個Python程序都是從第一行開始,順序執行,直到程序的最後一句。其中碰到def關鍵字進行函數定義的時候,所做的工作是“定義一個函數”,而不是“執行一個函數”。所以函數真正的執行並不是在定義的時候,而是在函數被調用的時候

自己練習輸入一下上面的程序,看看計算結果是什麽?

? 上面的自定義函數中,line是函數名。Python語言對自定義函數名的要求,跟變量名是相同的,也既:使用字母開始,後面可以有數字或者下劃線,不能包含別的字符。事實上函數也是變量的一種,這個概念我們的課程暫不涉及,你知道有這回事就好了。

? 學了今天的課程,實際上變量名、函數名的選取有了更多的要求:

  • 不能使用Python的關鍵字(保留字)
  • 不能使用同本程序引用的其它函數重復的名字
  • 簡單易懂,使用有意義的單詞或者拼音名。並且在每個單詞或者拼音開始的第一個字母之前使用下劃線或者大寫第一個字母
  • 比如:ji_suan / countTotalData

學習了自定義函數,來做個練習吧。就是把上面的應用題,用函數的形式重寫一遍。其中的計算部分,定義成1個或者2個函數來完成計算。

? 最後關於函數還有幾點要知道:

  • 函數的參數,通常就是用作函數的傳入參數,一般不用做返回值
  • 函數的返回值通常都要使用return來返回
  • 這是良好的編程習慣上需要的,並非語法上的規定。特別必要的情況下,也可以利用參數返回計算結果,我們將來會做介紹

變量的作用域

? 變量的概念和使用很簡單,函數的定義和使用也很簡單,當兩者出現在一起的時候,問題就復雜了。

? “全局變量”概念:在一個程序文件中,在最高層級的位置(就是語句前面沒有任何空格或者TAB鍵的層級),定義的變量,在程序的任何位置都是有效的。看一個例子:

x = 10

def testVar():
    print(x)

testVar()
print(x)

? 程序執行的輸出結果是:

10
10

? 第一個是10是自定義函數testVar中的print(x)語句輸出的。第二個10是程序結尾的print(x)輸出的。這個變量x就是全局變量,可以看到x不管在函數的內部還是外部,都能被有效的訪問到。再看一個例子:

x = 10

def testVar():
    x = 3
    print(x)

testVar()
print(x)

? 執行後程序的輸出是:

3
10

? 3是由自定義函數testVar輸出的,其中對x使用立即數3進行了賦值。10則依然是由程序最後一句輸出的。你可能感覺到奇怪,第一行輸出3不奇怪,奇怪的是為什麽函數調用完成後,x的值又變回了10呢?
實際上,在testVar函數中,x=3並不是再次對x進行賦值,而是在函數內重新定義了一個變量x。雖然這個x跟一開始的x同名,但這裏實際是個testVar函數的“局部變量”,在局部變量跟全局變量重名的情況下,全局變量會被隱藏,這說明局部變量的優先級要高於全局變量。同時,這個局部變量也只在testVar函數內部有效,不能在函數外使用。這也是“局部變量”這個名稱的由來。我們可以進一步再試一下:

def testVar():
    x = 3
    print(x)

testVar()
print(x)

? 執行結果是:

3
Traceback (most recent call last):
  File "var3.py", line 6, in <module>
    print(x)
NameError: name ‘x‘ is not defined

? 請看,在testVar函數執行中,局部變量x被正確顯示了。而函數返回後,在全局並不存在一個名為x的變量,所以Python報錯了。

? 那麽想在一個自定義函數內,直接修改全局變量的值怎麽辦?首先我們不建議這樣做,因為這樣會降低函數的“可重用性”,本來一個函數就可以看做一個積木的模塊,一個大的程序由很多小的積木塊拼裝起來。
這些“積木塊”應當有足夠的獨立性,從而可以在不同的程序中隨意拼裝,但是在函數內對外部的全局變量進行修改,等於是給“積木塊”在別的程序中使用預設了條件,這是很不好的編程習慣。
如果一定要這樣做呢?可以在自定義函數一開始就使用“global”關鍵字聲明變量,Python就會把該變量當做全局變量來使用了:

x = 10
def testVar():
    global x
    x = 3
    print(x)

testVar()
print(x)

? 程序的運行結果是:

3
3

? 這表示因為使用global在testVar函數內聲明了變量x,Python即便在testVar函數內,也把x當做全局變量來使用了,並沒有新建一個局部的x函數,因此對x的修改是全局性的,所以在程序最後一行顯示出來的,是testVar函數內對變量的修改內容。

? 這就是變量的作用域概念,全局變量還有局部變量。關於局部變量還有一點要補充:我們前面在函數自定義的時候就認識到了,函數的參數,在函數內部就是當做變量來使用的,也屬於局部變量,所以通常只用做輸入值,不用做返回值。最後看一個綜合的例子:

a = 1
b = 2
x = 3

def testVar(b):
    global a
    c=4
    print(a,b,c,x)
    a = 15
    print(a,b,c,x)

print(a,b)
testVar(5)
print(a,b)

學習英語,分為聽、說、讀、寫四大技能。掌握Python,重要的是讀和寫的練習。
仔細的思考10分鐘,閱讀程序,用自己的大腦模擬計算機的執行,寫出執行結果,然後再跟實際的執行結果來對比,看看自己的思考都正確嗎?


本講小結

  • 程序就是人與計算機溝通的語言,同人與人之間溝通的語言並沒有本質上的區別。
  • 本講介紹了使用IDLE編寫Python程序,最簡單的程序可以只有一行。
  • 程序可以順序編寫,但為了更好管理,通常有很多個小的函數組成。這個過程就好像是準備一個個的積木塊,然後把積木拼接起來。
  • 因為這個原因,自定義函數就好像準備最基本的一個積木塊,會經常用到,一定要弄明白。
  • 全程序必須使用統一的縮格格式,是新手比較容易犯錯的地方
  • 變量的作用域是較難理解、容易出錯而又很重要的概念,需要用心弄懂。

? 從今天起的內容,感覺上突然量增大了。每節課都會出現很多新的、不容易理解的概念。不要緊張,剛剛接觸編程的每個人都是這種感覺,隨著課程深入,你會逐漸適應的。多練習,在練習中發現自己的學習漏洞,通過實驗或者咨詢老師找到答案會讓你進步更快。


練習參考答案

? 請參考資料包中的ex2.py及ex2a.py兩種方案。

? 變量作用域最後一個綜合案例的執行結果,請一定要自己思考過後再看答案:

1 2
1 5 4 3
15 5 4 3
15 2

從零開始學習PYTHON3講義(三)寫第一個程序