天天看點

《從問題到程式:用Python學程式設計和計算》——2.10 若幹Python機制及其他

本節書摘來自華章計算機《從問題到程式:用python學程式設計和計算》一書中的第2章,第2.10節,作者:裘宗燕 更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

作為本章最後一節,這裡先簡單地回顧一下已經讨論的python基本機制和相關程式設計技術,然後介紹若幹前面沒有讨論的python功能。

2.10.1 已讨論的python機制

首先總結一下已經讨論過的基本語句,它們用于描述基本操作:

指派語句。這是最常用的基本語句。

表達式語句。可以在一個程式行中隻寫一個表達式,可以是任何計算表達式,最常見的是函數調用(如調用print。函數調用是表達式)。執行時解釋器求值該表達式。如果在互動方式中求值,解釋器将顯示得到的結果;在非互動方式下,解釋器求值這種表達式之後,就簡單地把結果抛棄。

break、continue、return語句,用于循環控制或函數傳回值。

import語句,用于導入程式包裡提供的功能。

除了這些簡單語句外,python還提供了一組用于控制語句執行程序的結構語句,包括if、for和while。它們是複合語句,因為它們都包含一個、兩個或多個作為成分的語句,其執行中的主要行為就是控制這個(這些)成分語句的執行。

另一主要機制是def語句,這種語句的執行将建立起一個函數(注意,在python裡函數也是對象,稱為函數對象),并将其限制于def語句中給定的函數名。一個函數包裝起一段稱為函數體的程式代碼。一個函數定義被執行後(函數定義好之後),就可以通過該函數的名字調用所定義的函數了。在函數體裡可以寫任何語句,包括調用其他函數。

這些就是python的基本程式設計機制,本書後面的大部分内容都圍繞着這些機制的使用,讨論關于如何使用它們去解決各種計算問題。今後讨論中展示的執行個體多為函數定義,其使用和結果則較少給出,以節約篇幅。由于本書提供了所有執行個體程式代碼,所定義函數的具體執行留給讀者自己完成。

2.10.2 若幹python機制

在繼續研究程式設計和用程式設計的方式解決問題之前,現在介紹幾種前面沒有讨論的程式設計機制。這些機制都不是根本性的,沒有它們也能寫出所有的程式。但這些機制在一些情況中很有用,有些就是為了簡化程式的書寫。

pass語句

pass語句也是一種基本語句,形式上隻包含關鍵字pass。這個語句執行時什麼也不做,立即結束。這種語句的作用類似于整數中的0、字元串中的空串等,表示某種最基本的情況。在實際程式裡,pass語句通常用于填補文法結構。如果某種結構要求一個語句成分,但實際程式中不需要做任何操作,就可以用pass填補空白。

擴充指派運算符

指派語句還有擴充的形式,下面兩種也比較常用:

第一種形式用于把一個表達式的值賦給多個變量(可以有任意多個,其中的 …… 表示其他變量)。這種指派語句同樣要求先求出表達式的值,而後把該值賦給左邊的所有變量。第二種形式要求把一串表達式的值分别賦給一串變量,這裡要求變量和表達式的個數相同,解釋器将順序求值各個表達式,然後按位置給對應的變量指派。

由于程式中經常需要寫諸如n = n + 1或x = x 2一類語句,也就是說,基于一個變量的原值,用一個運算算出新值,最後用這個新值更新變量。具體的例子如前面fact函數裡的prod = prod k等。在這種描述中,被使用和更新的變量出現了兩次。後面還會看到,變量還有更複雜的描述形式,減少這種重複書寫也有價值。

為處理這個問題,python提供了一組擴充指派符,其功能相當于做一次二進制運算,再用運算結果更新變量。針對每個二進制運算符各有一個組合指派符:

《從問題到程式:用Python學程式設計和計算》——2.10 若幹Python機制及其他

https://yqfile.alicdn.com/3c57df2cb3335ed6df3c30c63eb6f93c773d8510.png" >

這些操作的作用都是原地更新,即,直接修改這些指派符左邊的變量。最後幾個運算符沒有合适的名字,寫出的名字隻供參考,後面讨論中也不會使用。舉兩個例子:從效果看,prod = k就相當于prod = prod k;語句n += 1的效果是使變量n的值比語句之前增加了1。用這些指派符寫出的語句也作為指派語句看待。

上述運算符很有用,例如前面的階乘函數現在可以重新寫為:

上面說,例如,prod = k與prod = prod k等價,這是從語義效果講。但解釋器完全可以對一些情況采用更優異的實作方法。例如,許多硬體有更新寄存器的專門指令,如果解釋器利用它們,前者的效率可能更高。是以,如果要做基于變量原值的更新,而某個擴充指派運算符正好合用,就應該使用它。書寫上更簡單,意義更明确清晰,還可能執行效率更高,何樂而不為呢?

請讀者檢查前面的程式執行個體,看看哪些程式可以改用這些指派符。在後面章節裡,很多地方都可以看待這類指派符的使用。

條件表達式

python還有一種特殊的帶條件的表達式,用于描述在不同情況下采用不同規則求值的情況。條件表達式也是表達式,每個條件表達式計算出一個值。

條件表達式的形式是:

其中條件部分描述某種邏輯關系。這種表達式的語義(求值的方式)是:首先求值條件,如果其值為真就求值表達式1,以其值作為整個條件表達式的值;當條件不真時求值表達式2,并以其值作為整個表達式的值。

下面是基于條件表達定義的求絕對值函數:

定義很簡單。雖然abs是内置函數名,但這個辨別符并不是關鍵字,這裡重新定義也是合法的。當然,這裡隻是作為例子,實際中人們一般不這樣做。

有關條件表達式,有兩個問題需要注意。首先,如果求值一個條件表達式,其兩個成分表達式中隻有一個會被實際求值。例如,下面語句不會出現除0錯誤:

還應注意條件表達式與條件語句的不同。語句沒有值,執行時産生“效果”,表達式的計算就是求值。用條件語句定義abs函數,應寫為:

比較一下,用條件表達式寫出的定義更緊湊。在友善的時候,适當地使用條件表達式也是很好的選擇。

2.10.3 python解釋器

最後簡單總結一下python解釋器的工作方式。

python系統(解釋器)處理程式時,基本方式是按行讀入和處理:

預設方式是按行處理,遇到換行時就認為語句(或表達式)結束,就會去執行這個語句(或求值表達式)。是以程式不能随意地在語句(或表達式)中間換行。

如果在讀入一行的最後遇到反斜線符号 ,解釋器就丢掉反斜線符及随後的換行符,把下一行的内容看作是本行内容的繼續(續行)。

如果被讀入行中存在尚未配對的括号,同樣認為下一行是本行的繼續。

以換行結尾的一系列字元構成一個實體(的程式)行,解釋器将根據上面規則把連續幾個實體行拼接成一個邏輯的程式行(邏輯行),一次處理一個邏輯行。

如果讀到的行是一個複雜結構的頭部,解釋器就會繼續讀完這個結構(根據代碼的倒退形式),而後一次完成這個結構的處理。

在互動式的工作方式下,python解釋器的基本處理循環中順序做三件事:

讀入一個邏輯的程式行,或者一個跨越幾行的複雜結構,如def、if、for、while等複雜結構;

處理讀入的結構(完成它要求的操作);

輸出計算結果(如果有非none結果),或者報錯。

處理子產品中的代碼時,解釋器也采用同樣處理規則,隻是不顯示求值結果。