第2章
軟體開發、資料類型和表達式
完成本章的學習之後,你将能夠做到以下幾點:
● 描述軟體開發的基本階段:分析、設計、編碼和測試。
● 使用字元串作為終端輸入和輸出文本。
● 在算術運算中使用整數和浮點數。
● 構造算術表達式。
● 初始化并使用具有适當名稱的變量。
● 從庫子產品導入函數。
● 使用參數調用函數并适當地使用傳回值。
●構造一個執行輸入、計算和輸出的簡單Python 程式。
●使用文檔字元串記錄Python 程式。
本章首先讨論軟體開發過程,然後是一個案例研究,通過這個案例我們将介紹程式的分析、設計、編碼和測試等步驟。還将研究構成程式的基本元素,主要包括文本和數字的資料類型以及操縱它們的表達式。本章最後介紹簡單程式中函數和子產品的使用。
2.1 軟體開發過程
程式設計比編寫代碼行要複雜得多,就像建造房屋比敲釘子要複雜得多一樣。“複雜得多”包括組織和規劃,以及編制這些計劃的各種慣例。計算機科學家将計劃群組織程式的過程稱為軟體開發。軟體開發有幾種方法,其中之一被稱為瀑布模型。
瀑布模型由幾個階段組成:
1. 客戶請求:在這一階段,程式員會收到一份關于問題的廣泛陳述,該問題有可能适用于計算機化的解決方案。這個步驟也稱為使用者需求階段。
2. 分析:程式員決定程式将做什麼。這有時被視為澄清問題規格的過程。
3. 設計:程式員決定程式如何完成任務。
4. 實作:程式員編寫程式。這個步驟也稱為編碼階段。
5. 內建:大型程式有許多部分。在內建階段,這些部分被整合成一個平穩運作的整體,這通常不是一件容易的事情。
6. 維護:程式通常具有較長的壽命,軟體的壽命約為5至15年。在此期間,需求會發生變化,會檢測到錯誤,并會進行或小或大的修改。
瀑布模型的各個階段如圖2-1 所示。正如你所看到的,該圖類似于瀑布,其中每個階段的結果向下流動到下一個階段。然而,在一個階段檢測到的錯誤通常要求開發人員備份和重做前一階段的一些工作。維護期間所做的修改也需要備份到早期階段。總而言之,這些階段也被稱為軟體開發生命周期。

雖然圖中描述了不同的階段,但這并不意味着開發人員必須在編碼之前分析和設計一個完整的系統。現代軟體開發通常是增量的和疊代的。這意味着,分析和設計可能會産生一個粗略的草稿、骨架版本或系統原型,這些可用于編碼階段,然後在一些測試後備份到早期階段,以填充更多的細節。然而,為了介紹這一過程,我們将這些階段視為不同的階段。
程式在第一次運作時很少像希望的那樣工作,是以,它們應該接受廣泛而仔細的測試。許多人認為測試是一項僅适用于實作和內建階段的活動,然而,你應該仔細檢查每個階段的産出。記住,早發現的錯誤比晚發現的錯誤的成本要小得多。圖2-2 說明了在不同階段發現錯誤時修複錯誤的一些相對成本。這些不僅是财務成本,也是時間和勞動力的成本。
請記住,開發軟體的成本并沒有在各個階段平均分攤,圖2-3 所示是典型的百分比。
你可能認為實作花費的時間最多,是以成本最高。然而,如圖2-3 所示,維護是軟體開發中最昂貴的部分。通過仔細分析、設計和實作,可以降低維護成本。
當你閱讀這本書并開始提高程式設計技能時,應該記住以下兩點:
● 軟體開發不僅僅是編寫代碼。
● 如果想降低軟體開發的總體成本,就要編寫易于維護的程式。這需要徹底的分析、仔細的設計和良好的編碼風格。我們将在整本書中對編碼風格做更多的論述。
■.練習
- 列出軟體開發過程的四個階段,并解釋它們完成了什麼。
- 傑克說,他不會費心進行分析和設計,而是直接開始編寫程式。為什麼這不是個好主意?
2.2 案例研究:所得稅電腦
本書的大部分章節都包含說明軟體開發過程的案例研究。對于小程式來說,這種方法似乎過于複雜,但是當程式變大時,它會擴充得很好。第一個案例研究開發了一個計算所得稅的程式。
每年,幾乎每個有收入的人都面臨着計算所得稅申報表的不愉快任務。但願它能像本案例研究中建議的那樣容易完成!我們從客戶請求階段開始。
-->請求
客戶請求一個計算個人所得稅的程式。
-->分析
分析經常要求程式員學習一些關于問題領域的東西,本例中指的就是相關的稅法。為了簡單起見,我們假設有以下稅法規定:
●所有納稅人都被征收20% 的統一稅率。
●所有納稅人都可以享受10 000 美元的标準扣除。
●對于每個受撫養人,允許納稅人額外扣除3000 美元。
● 總收入在輸入時必須精确到便士。
● 所得稅以十進制數表示。
分析的另一部分決定了使用者必須提供什麼資訊。在本例中,使用者需要輸入的是總收入和家庭人數。該程式根據輸入和稅法計算所得稅,然後顯示所得稅。圖2-4 顯示了拟建的終端界面。斜體字元表示使用者輸入,其餘部分由程式列印。在這裡,包含互動界面是一個好主意,因為它允許客戶和程式員在雙方都能了解的上下文中讨論程式的預期行為。
-->設計
在分析期間,我們指定了程式将要做什麼。在下一階段,即設計階段,我們将描述程式如何執行,這通常包括編寫算法。在第1 章中,我們展示了如何用普通英語編寫算法。事實上,算法常常是用一種有點程式化的英文版本寫的,稱為僞代碼。以下是所得稅程式的僞代碼:
雖然沒有精确的規則來規範僞代碼的文法,但是在僞代碼中,應該盡量以清晰簡潔的方式描述程式的基本元素。請注意,這個僞代碼非常類似于Python 代碼,是以到編碼步驟的轉換應該很簡單。
-->實作(編碼)
給定前面的僞代碼,經驗豐富的程式員現在會發現編寫相應的Python 程式很容易。另一方面,對于初學者來說,編寫代碼可能是這個過程中最困難的部分。盡管按照大多數标準,接下來的程式很簡單,但不要期望一開始就能了解其中的每一點。本章的其餘部分解釋
了關于編碼的更多細節。
-->測試
所得稅計算程式可以作為一個腳本在IDLE 視窗運作。如果沒有文法錯誤,我們将能夠鍵入一組輸入并檢視結果。然而,一次沒有文法錯誤并輸出正确的運作,隻提供了關于程式正确性的輕微訓示。隻有經過徹底的測試才能說明程式正常工作。測試是一個深思熟慮的過程,需要程式員進行一些規劃和訓練。在第一次成功運作後,為了滿足截止日期或者繼續下一個任務,馬上送出程式會容易得多。但是你的工作或使用者的生活可能會受到馬虎的軟體測試的影響。
可以從IDLE 視窗輕松執行測試。程式員隻需要将程式反複加載到外殼中,并輸入不同的輸入集。真正的挑戰是提出一組能夠揭示錯誤的輸入。此時的錯誤也稱為邏輯錯誤或設計錯誤,是意外的輸出。
正确的程式會為任何合法的輸入産生預期的輸出。所得稅電腦的分析并沒有說明哪些輸入是合法的,但是常識表明它們是大于或等于0 的數字。其中一些輸入将産生小于0 的輸出,但是我們現在假設這些輸出是符合預期的。即使計算機上輸入數字的範圍有限,測試所有可能的輸入組合也是不切實際的。挑戰是找到一個更小的輸入集,稱為測試套件,從中我們可以得出結論——該程式很可能對所有輸入都是正确的。在稅收項目中,我們嘗試輸入0、1 和2 作為受撫養人的數量。如果程式能正确處理這些,我們可以假設它能正确處理較大的值。總收入的測試輸入是一個等于标準扣除額的數字,以及這個數字的兩倍(分别為10 000 和20 000 )。這兩個值将顯示最低預期稅(0)和預期稅小于或大于0 的情況。程式在兩個輸入的每個可能組合下運作。表2-1 顯示了測試套件中輸入和預期輸出的可能組合。
如果代碼中存在邏輯錯誤,那麼使用這些資料幾乎肯定會被捕獲。請注意,負輸出不被視為錯誤。我們将在下一章中看到如何防止這種計算。
2.3 字元串、指派和注釋
文本處理是迄今為止最常見的計算應用。電子郵件、文本消息、網頁和文字處理都依賴和操縱由字元串組成的資料。本節介紹使用字元串輸出文本和Python 程式文檔。我們首先介紹一般的資料類型。
2.3.1 資料類型
在現實世界中,我們總是使用資料,而不用考慮使用的是哪種資料。例如,考慮這句話:“2007年,米凱拉為她在東楓樹街24号的房子支付了12萬美元。”這句話至少包括四項資料——名字、日期、價格和位址,但是你當然不必在說出這句話之前停下來想一想。你不必考慮名字隻包含文本字元,日期和房價是數字,等等。然而,在計算機程式中使用資料時,我們确實需要記住自己使用的資料類型。我們還需要記住可以對特定資料做什麼(可以對特定資料執行什麼操作)。
在程式設計中,資料類型由一組值和一組可對這些值執行的操作組成。Python 中的字面量是指資料類型的值對程式員來說的樣子。程式員可以在程式中使用字面量來提及資料值。當Python 解釋器對字面量求值時,它傳回的值就是字面量。表2-2 顯示了幾個Python 資料類型的示例字面量。
表2-2 中列出的前兩種資料類型int和float被稱為數字資料類型,因為它們代表數字。本章稍後将詳細介紹數字資料類型。目前,我們先關注字元串。
2.3.2 字元串字面量
在Python 中,字元串字面量是用單引号或雙引号引起來的字元序列。Python shell 的以
下代碼顯示了一些示例字元串:
最後兩個字元串字面量(' ' 和"")表示空字元串。雖然不包含字元,但空字元串仍然是字元串。注意,空字元串不同于包含單個空格字元的字元串。雙引号字元串對于包含單引号或撇号的字元串來說非常友善。下面是一個例子:
注意,print函數顯示嵌套引号,但不顯示封閉引号。如果使用單引号将字元串字面量引起來,則雙引号也可以包含在字元串字面量中。
當你用Python 代碼編寫字元串字面量,并作為輸出顯示在螢幕上時,需要确定是将字元串作為單行還是多行段落輸出。如果要将字元串作為單行輸出,必須在同一行代碼中包含全部字元串字面量(包括其開頭和結尾引号),否則将發生文法錯誤。要輸出包含多行的文本段落,可以對每行使用單獨的print 函數調用。但是,将整個字元串字面量、換行符和所有内容包含在三個連續的引号(單或雙)内以進行列印會更友善。以下代碼展示了如何做到這一點:
注意,輸出中的第一行恰好在代碼第一行結束的地方結束。當你在Python shell 中計算不帶print功能的字元串時,可以看到嵌入結果中的換行符n的字面量,如下所示:
2.3.3 轉義序列
換行符n被稱為轉義序列。轉義序列是Python 将特殊字元(如制表符、換行符和倒退符)表示為字面量的方式。表2-3 列出了Python 中的一些轉義序列。
因為反斜杠用于轉義序列,是以它必須被轉義為字元串中的字面量字元。是以,
将顯示單個字元。
2.3.4 字元串連接配接
可以使用串聯運算符“+”連接配接兩個或多個字元串以形成新的字元串。下面是一個例子:
而“
”運算符允許你通過重複給定次數的另一個字元串來建構一個字元串。左操作數是字元串,右操作數是整數。例如,如果你希望字元串前面有10個空格,使用1個空格、
運算符和數字10比手工輸入10個空格更容易。下面的代碼展示了使用
和+運算符來實作這一結果:
2.3.5 變量和指派語句
正如我們在第1 章中看到的,變量将名稱與值相關聯,進而便于以後在程式中記住和使用該值。為變量選擇名稱時,需要注意一些規則。例如,某些名稱(如if 、def 和import)已保留用于其他目的,是以不能用于變量名。通常,變量名必須以字母或下劃線(_)開頭,并且可以包含任意數量的字母、數字或其他下劃線。Python 變量名區分大小寫,是以,變量WEIGHT 不同于變量weight 。Python 程式員通常使用小寫字母作為變量名,但是在變量名由多個單詞組成的情況下,變量名中的每個單詞(第一個單詞除外)通常都以大寫字母開頭。這使得變量名更容易閱讀。例如,名稱interestRate 比名稱interestrate 稍微容易閱讀一些。
程式員将全大寫字母用于從不改變的值的變量名。這些變量被稱為符号常數。所得稅電腦案例研究中的符号常數示例有TAX RATE 和STANDARD DEDUCTION 。變量接收初始值,并且可以用指派語句重置為新值。指派語句最簡單的形式如下:
如第1章所述,尖括号中的術語命名或描述Python 代碼構造的一部分。是以,符号
代表任何Python 變量名,例如totalIncome 或taxRate。符号
代表任何Python 表達式,例如
。
Python 解釋器首先計算指派符号右側的表達式,然後将左側的變量名綁定到該值。當變量名第一次發生這種情況時,被稱為定義或初始化變量。請注意,“=”符号表示指派,而不是相等。初始化變量後,表達式中變量名的後續使用稱為變量引用。
當解釋器在任何表達式中遇到變量引用時,它會查找相關聯的值。如果名稱在被引用時尚未綁定到值,Python 會發出錯誤信号。以下代碼展示了變量及其引用的一些定義:
前兩個語句将變量
和
初始化為字元串值。下一條語句引用這些變量,連接配接變量引用的值以建構新字元串,并将結果配置設定給變量
(“連接配接”表示“黏合在一起”)。最後一行代碼是對變量
的簡單引用,該變量傳回其值。
變量在程式中有兩個重要目的:幫助程式員跟蹤随時間變化的資料,還允許程式員用簡單的名字引用複雜的資訊。任何時候,如果可以用一個簡單的東西代替一個更複雜的東西,就可以讓程式員更容易了解和維護程式。這種簡化過程被稱為抽象,這是計算機科學的基本思想之一。在這本書中,你将了解計算中使用的其他抽象,包括函數、子產品和類。
聰明的程式員選擇的名字讓别人很容易知道資料的用途,這反過來又使程式更容易維護和排除故障。優秀的程式不僅能正确執行任務,而且讀起來就像一篇文章,其中每個單詞都被仔細地選擇以向讀者傳達适當的意思。例如,一個為簡單的利息貸款建立支付計劃的程式可能會使用變量
2.3.6 程式注釋和文檔字元串
我們在關于字元串的這一節結束時讨論程式注釋。注釋是計算機忽略的一段程式文本,但它為程式員提供了有用的資訊。至少,程式的作者可以在程式檔案的開頭包括自己的名字以及關于程式目的的簡短聲明。這種類型的注釋稱為文檔字元串,是本節前面讨論過的多行字元串形式。下面的例子是開始一段程式的典型文檔:
除了文檔字元串,行尾注釋也可以對程式進行說明。這些注釋以符号# 開始,延伸到一行的末尾。如果代碼的含義不明顯的話,行尾注釋可以解釋變量的目的或者它所使用的政策。下面是一個例子:
在程式中,好的文檔可能和可執行代碼一樣重要。理想情況下,程式代碼是自我說明的,是以我們可以立即了解它。然而,程式經常會被他人閱讀,甚至作者在幾個月沒有看到代碼之後可能會發現自己的代碼不可思議。訣竅是,避免注釋含義清晰的代碼,但是當代碼本身可能無法提供足夠清晰的含義時,用注釋幫助那些一頭霧水的讀者。考慮到這個目的,做以下事情是一個好主意:
● 開始一段程式時,要陳述其目的等相關資訊,這些資訊将有助于指導程式員在未來某個日期修改程式。
● 在變量定義後,附上解釋變量目的的注釋。
● 在代碼的主要部分之前,用簡短的注釋解釋其目的。本章前面介紹的案例研究就是這樣做的。
● 用注釋來解釋複雜或棘手的代碼部分的工作原理。
1.設變量x 為"dog",變量y 為"cat" 。寫出下列操作傳回的值:
2.使用嵌入的換行符在單獨的一行内寫一個包含你的名字和位址的字元串。然後,不使用換行符寫一個相同的字元串字面量。
3.如何在字元串字面量中将包含的撇号作為字元?
4.當print 函數列印嵌入換行符的字元串字面量時會發生什麼?
5.下列哪一個是有效的變量名?
6.說明程式文檔的兩個目的。
2.4 數字資料類型和字元集
計算機最初的應用是用來處理數字的。雖然文本和媒體處理最近變得越來越重要,但是在許多應用中數字仍然非常重要。在本節中,我們簡要概述數字資料類型及其變體——字元集。
2.4.1 整數
正如你在數學中所學的,整數包括0、正整數和負整數。Python 程式中的整數字面量沒有逗号,前導負号表示負值。雖然整數的範圍是無限的,但是計算機的記憶體限制了最大正整數和最大負整數的數量。在許多程式設計語言中,int資料類型最常見的實作方式包括從-2 147 483 648(-231)到2 147 483 647(231-1)的整數。但是,Python 整數的大小要大得多,并且僅受計算機記憶體的限制。作為一項實驗,嘗試計算表達式
,它将最大正int值提高到100 次方。你會看到一個包含很多行數字的數!
2.4.2 浮點數
數學中的實數由整數、小數點和小數部分組成,如π的值是3.1415…。實數具有無限精度,這意味着小數部分的數字可以永遠延續下去。像整數一樣,實數也有無限的範圍。然而,因為計算機的記憶體不是無限大的,是以不僅限制了範圍,也限制了實數的精度。Python 使用浮點數來表示實數,float 類型最常見的值的範圍從大約-10308 到10308,精度為16 位。
浮點數可以用普通的十進制記數法或科學記數法來表示。科學記數法通常對表示非常大的數字很有用。表2-4 顯示了用這兩種記數法表示的相同的值。
2.4.3 字元集
一些程式設計語言對字元串和單個字元使用不同的資料類型。在Python 中,字元字面量看起來就像字元串字面量一樣,屬于字元串類型。為了展現本書的不同之處,我們使用單引号包覆單個字元,使用雙引号包覆多個字元。是以,我們稱‘H’為一個字元,“Hi!”為一個字元串,盡管在技術上它們都是Python 字元串。
正如你在第1章中所學到的,在真正的計算機上運作之前,程式中的所有資料和指令都被翻譯成二進制數。為了支援這種轉換,字元串中的每個字元都映射到一個整數值。這個映射在字元集中定義,其中包括ASCII 集和Unicode 集。(術語ASCII 代表美國資訊交換标準代碼。)20 世紀60 年代,最初的ASCII 集使用從0 到127 的整數對每個鍵盤字元和幾個控制字元進行編碼。控制字元的一個例子是Control + D ,它是終止shell 視窗的指令。随着新功能鍵和一些國際字元被添加到鍵盤上,20 世紀80 年代中期ASCII 集的大小增加了一倍,達到256 個不同的值。然後,當從英語以外的語言添加字元和符号時,20 世紀90 年代早期建立了Unicode 集來支援65 536 個值。Unicode 目前支援超過128 000 個值。
表2-5 顯示了字元值到前128 個ASCII 碼的映射。左列中的數字代表ASCII 碼最左邊的數字,而最上面一行中的數字是最右邊的數字。是以,第8 行第2 列的字元R 的ASCII 碼是82。
有些人可能會覺得在數字類型的讨論中包含字元很奇怪。然而,正如你所看到的,ASCII 字元集映射到一組整數。Python 的ord和chr函數分别将字元轉換為數字ASCII 碼,然後再傳回。下面的代碼使用這兩個函數來探索ASCII 系統:
注意,'B' 的ASCII 碼是序列中'A' 之後的下一個數字。這兩個函數提供了一種友善的方式來将字母移動固定的距離。例如,如果你想将字母'A' 向右移三個位置,可以寫作
- 哪種資料類型最适合用來表示以下資料值?
- 一年中的月數
- 圓的面積
- 現行最低工資
- 宇宙的大約年齡( 12 000 000 000年)
- 你的名字
- 解釋資料類型int 和float 之間的差異。
- 用Python 的科學記數法寫以下浮點數的值:
- 355.76
- 0.007 832
- 4.3212
- 參考表2-5 寫出字元'$' 和'&' 的ASCII 值。
2.5 表達式
正如我們已經看到的,字面量會對自身進行求值,而變量引用會對變量的目前值進行求值。表達式提供了一種對資料值執行操作以生成其他資料值的簡單方法。你之前看到了在表達式中使用的字元串。當在Python shell 提示符下輸入時,将計算表達式的操作數,然後将其運算符應用于這些值以計算表達式的值。在本節中,我們将更詳細地研究算術表達式。
2.5.1 算術表達式
算術表達式由操作數和運算符組成,這些操作數和運算符的組合方式是你在代數課程中已經熟悉的。表2-6 顯示了幾個算術運算符,并舉例說明了如何在Python 代碼中使用它們。
在代數中,你可能習慣于這樣表示乘法:ab。然而,在Python 中,必須使用乘法運算符“
”明确表示乘法,如a
b。二進制運算符放在其操作數之間(例如a
b),而一進制運算符放在其操作數之前(例如-a)。在Python 中計算算術表達式時,你在代數中學習的優先規則同樣适用:
● 幂運算具有最高的優先級,首先計算。
● 接下來,在乘法、除法和取餘之前,進行一進制求反計算。
● 乘法、除法、商和取餘都要在加、減法之前進行計算。
● 在指派之前,對加法和減法進行計算。
● 同等優先級的操作是左結合的,是以它們是從左到右計算的。幂運算和指派運算是右結合的,是以這些運算的連續執行個體是從右向左計算的。
●可以使用括号更改運算的順序。表2-7 顯示了一些算術表達式及其值。
表2-7 的最後兩行顯示了除以0 的嘗試,這将導緻錯誤。這些表達式很好地說明了文法和語義之間的差別。文法是一套規則,用于在語言中建構格式良好的表達式或句子。語義是一組規則,允許智能體解釋這些表達式或句子的含義。當一個表達式或句子的格式不正确時,計算機會産生文法錯誤。當表達式描述的動作無法執行時,即使該表達式在文法上是正确的,也會檢測到語義錯誤。雖然表達式45/0和45%0在文法上是正确的,但是它們沒有意義,因為計算智能體不能執行它們。當人類用自然語言交談時,可以容忍各種文法錯誤和語義錯誤。相比之下,計算智能體不能容忍這些錯誤。
除了精确除法之外,當算術表達式的兩個操作數都是相同的數字類型(int或float)時,得到的值也是該類型。當兩個操作數屬于不同類型時,結果值屬于更通用的類型。注意,float型比int型更通用。商運算符/ / 産生整數商,而精确除法運算符/ 總是産生浮點數。是以,3//4結果為0,而3/4結果為.75。
雖然表達式中的間距對Python 解釋器來說并不重要,但是程式員通常在每個運算符前後各插入一個空格,以便于閱讀代碼。通常,表達式必須在一行Python 代碼上完成。當表達式變長或變複雜時,可以通過在目前行的末尾放置反斜杠字元來移動到新行。下面的例子展示了這種方法:
確定在運算符之前或之後插入反斜杠。如果在IDLE 中以這種方式換行,編輯器會自動正确縮進代碼。
正如你将很快看到的,也可以在逗号後立即中斷一長串代碼,示例包括帶有幾個參數的函數調用。
2.5.2 混合模式算術和類型轉換
你已經看到/ / 運算符如何産生整數結果,/ 運算符如何産生帶有兩個整數的浮點結果。當一個操作數是int而另一個是float時會發生什麼?在使用手持式電腦時,你不會過多考慮混合整數和浮點數的問題。執行包含整數和浮點數的計算稱為混合模式算術。例如,如果一個圓的半徑為3,則計算面積如下:
Python 如何執行這種類型的計算?在對不同數字類型的操作數進行二進制運算時,在執行運算之前,較不通用的類型(int)會暫時自動轉換為較通用的類型(float)。是以,在示例表達式中,數值9 在乘法之前被轉換為9.0。
處理數字輸入時,必須使用類型轉換函數。類型轉換函數是一個與它轉換到的資料類型同名的函數。因為input函數傳回一個字元串作為其值,是以在執行算術運算之前,必須使用函數int或float将字元串轉換為數字,如下例所示:
表2-8 列出了一些常見的類型轉換函數及其用途。
注意,int 函數通過截斷而不是舍入到最近的整數,将浮點數轉換為整數。截斷簡單地切斷了數字的小數部分。round 函數将浮點數舍入到最近的整數,如下例所示:
類型轉換的另一個用途是利用數字和其他字元串來構造字元串。例如,假設變量profit 指的是一個浮點數字,代表以美元和美分表示的金額。為了建構一個代表這個輸出值的字元串,我們需要将$ 符号連接配接到profit 值。但是,Python 不允許将+ 運算符與字元串和數字一起使用:
為了解決這個問題,我們使用str 函數将profit 值轉換為字元串,然後将這個字元串連接配接到$ 符号,如下所示:
Python 是一種強類型程式設計語言。解釋器在運算符應用于所有操作數之前檢查它們的資料類型。如果操作數的類型不合适,解釋器會停止執行,并顯示錯誤消息。這種錯誤檢查可防止程式嘗試做它不能做的事情。
- 令 x=8,y=2 。寫出以下表達式的值:
- x + y * 3
- (x + y) * 3
- x ** y
- x % y
- x / 12.0
- x // 6
- 令x = 4.66 ,寫出以下表達式的值:
- round(x)
- int(x)
- Python 程式員如何将浮點值舍入到最近的整數值?
- Python 程式員如何将數值連接配接到字元串值?
- 假設變量x 的值為55,使用指派語句将x 的值增加1。
2.6 函數和子產品的使用
到目前為止,在本章中我們已經研究了兩種操作表達式中資料的方法。可以對一個或多個操作數應用“+”等運算符來産生新的資料值。或者,可以用一個或多個資料值調用諸如round 之類的函數來産生新的資料值。Python 包含許多有用的函數,這些函數組織在稱為子產品的代碼庫中。在本節中,我們将研究函數和子產品的使用。
2.6.1 調用函數:參數和傳回值
函數是一個代碼塊,可以按名稱調用它來執行任務。函數通常需要參數即特定的資料值來執行任務。當一個函數完成任務(通常是某種計算)時,可以将結果發送回程式中最初調用該函數的部分。将結果發送回程式的另一部分的過程稱為傳回值。
例如,函數調用round(6.5) 中的參數是值6.5,傳回的值是7。當參數是表達式時,首先對其進行計算,然後将其值傳遞給函數進行進一步處理。例如,函數調用abs(4-5) 首先計算表達式4-5,然後将結果-1 傳遞給函數abs。最後,函數abs 傳回值1。
函數調用傳回的值可以在表達式和語句中使用。例如,函數調用print(abs(4-5)+3) 列印值4。
有些函數隻有可選參數,有些函數有必要參數,有些函數同時有必要參數和可選參數。例如,round 函數有一個必要參數,即要舍入的數字。當僅用一個參數調用時,round 函數顯示其預設行為,即傳回小數部分為0 的最近整數。但是,當提供第二個可選參數時,該參數(一個數字)訓示第一個參數應該舍入到的精确位置的數量。例如,round(7.563, 2) 傳回
7.56。
要了解如何使用函數的參數,請參考shell 中函數的文檔。例如,Python 的help 函數顯示了關于round 的資訊,如下所示:
傳遞給函數的每個參數都有特定的資料類型。編寫涉及函數及其參數的代碼時,需要記住這些資料類型。試圖将錯誤資料類型的參數傳遞給函數的程式通常會産生錯誤。例如,不能取字元串的平方根,而隻能取數字的平方根。同樣,如果将函數調用放在期望不同于函數傳回的操作數類型的表達式中,則會引發錯誤。如果你不确定與特定函數的參數關聯的資料類型,請閱讀文檔。
2.6.2 math 子產品
函數和其他資源被編碼在稱為子產品的元件中。__builtin__ 子產品中的abs 和round 等函數總是可以使用的,而程式員必須從定義它們的子產品中顯式導入其他函數。math 子產品包括幾個執行基本數學運算的函數。以下代碼導入math 子產品并列出其資源目錄:
這個函數名清單包括一些我們熟悉的三角函數以及Python 對常數π和e 的最精确預算。
要使用子產品中的資源,可以将子產品的名稱寫為限定符,後跟一個點(. )和資源的名稱。例如,要使用math 子產品中的pi 值,可以編寫以下代碼:math.pi。以下代碼使用此方法顯示π值和2 的平方根:
如果需要,還可以使用help:
或者,可以通過輸入help(math) 浏覽整個子產品的文檔。函數help 使用子產品自己的文檔字元串及其所有函數的文檔字元串來列印文檔。
如果要頻繁使用子產品的幾個資源,可以通過導入各個資源來避免在每個引用中使用限定符,如下所示:
程式員偶爾會導入一個子產品的所有資源,在沒有限定符的情況下使用。例如,語句from math import * 将導入math 子產品的所有資源。
通常,首選導入資源的第一種方法(即僅導入子產品的名稱)。子產品限定符的使用不僅提醒讀者函數的目的,還幫助計算機區分同名的不同函數。
2.6.3 main 子產品
在本章前面的案例研究中,我們展示了如何為Python 腳本編寫文檔。為了差別這個腳本和程式中的其他子產品(可能有很多),我們稱它為main 子產品(主子產品)。像任何子產品一樣,主子產品也可以被導入。不是從終端提示符啟動腳本,也不是從IDLE 将腳本加載到shell 中,而是從終端提示符啟動IDLE,并将腳本作為子產品導入。我們用taxform.py 腳本來實作這一點,如下所示:
導入主子產品後,可以通過運作help 函數檢視其文檔:
2.6.4 程式格式和結構
現在是退後一步了解簡單Python 程式的整體格式和結構的好時機。按照以下方式構造程式是一個好主意:
● 從介紹性注釋開始,說明作者的姓名、計劃的目的和其他相關資訊。此資訊應該是文檔字元串的形式。
● 然後,包括執行以下操作的語句:
● 導入程式所需的任何子產品。
● 初始化重要變量,适當地注釋。
● 提示使用者輸入資料,并将輸入資料儲存在變量中。
● 處理輸入以産生結果。
● 顯示結果。
花點時間回顧一下本章開頭案例研究中介紹的所得稅項目。注意該程式如何符合這個基本組織結構。另外,請注意,程式的各個部分由空白(空行)分隔。記住,程式應該易于其他程式員閱讀和了解,應該像散文一樣适合閱讀!
2.6.5 使用終端指令提示符運作腳本
到目前為止,在本書中,我們一直在IDLE 中開發和運作Python 程式。當一個程式的開發和測試完成後,可以将其釋出給其他人在他們的計算機上運作。Python 必須安裝在使用者的計算機上,但是使用者不需要IDLE 來運作Python 腳本。
運作Python 腳本的一種方法是打開終端指令提示符視窗。在運作Windows 10 的計算機上,單擊工作列上的“在此處鍵入搜尋”框,鍵入“指令提示符”,然後單擊清單中的“指令提示符”。在早期版本的Windows 中,單擊“開始”按鈕,選擇“所有程式”,選擇“附件”,然後選擇“指令提示符”。在基于Macintosh 或UNIX 的系統上,你将看到一個終端視窗。Macintosh 上的終端視窗如圖2-5 所示。
使用者打開終端視窗後,必須導航或更改目錄,直到提示顯示已到達包含Python 腳本的目錄。例如,假設名為taxform.py 的腳本在終端目前目錄下的pythonfiles 目錄中,圖2-6 顯示了更改到該目錄并列出其内容的指令。
到達适當的目錄後,使用者可以通過在指令提示符下輸入指令python3 scriptname.py 來運作腳本(小心:如果運作python 而不是python3,你可能會啟動Python 2 的解釋器,它不會運作本書中的所有程式)。圖2-7 顯示了這個步驟和taxform 腳本的運作。
所有Python 安裝還提供了通過輕按兩下作業系統檔案浏覽器中的檔案來啟動Python 腳本的功能。在Windows 系統上,此功能是自動的,而在Macintosh 和基于UNIX 的系統上,則是.py 檔案類型必須設定為使用Python 啟動器應用程式啟動。但是,以這種方式啟動腳本時,指令提示符視窗會打開,顯示腳本的輸出,然後關閉。為了防止這種視窗問題,可以在腳本末尾添加一個input 語句,該語句會暫停,直到使用者按下Enter 或Return 鍵,如下所示:
- 解釋函數及其參數之間的關系。
- math 子產品包括一個pow 函數,它計算一個數字的給定的幂。第一個參數是數字,第二個參數是指數。編寫一個代碼段來導入這個函數并調用它來列印82 和54 的值。
- 解釋如何顯示給定子產品中所有函數的目錄。
- 解釋如何顯示給定子產品中特定函數的幫助資訊。
2.7 本章小結
● 瀑布模型按照幾個階段描述了軟體開發過程。分析決定了軟體會做什麼。設計決定了軟體将如何實作其目的。實作包括用特定程式設計語言對軟體進行編碼。測試和內建表明該軟體在釋出時完成了預期的工作。釋出後,維護會定位并修複錯誤,并為軟體添加新功能。
● 字面量是可以出現在程式中的資料值,它們對自己進行求值。
● 字元串資料類型用于表示輸入和輸出的文本。字元串是字元序列。字元串字面量用單引号或雙引号引起來。兩個字元串可以通過串聯組合形成一個新字元串。
● 轉義字元以反斜杠開頭,表示特殊字元,如删除鍵和換行符。
● 文檔字元串是由三個引号引起來的字元串,提供程式文檔。
● 注釋是一段代碼,解釋器不會對其進行求值,但是程式員可以閱讀它來擷取關于程式的資訊。
●變量是引用值的名稱。變量的值被初始化,可以通過指派語句重置。在Python 中,任何變量都可以被命名為任何值。
●int 資料類型表示整數。float 資料類型表示浮點數。整數或浮點數的大小受計算機記憶體的限制,浮點數的精度也是如此。
● 算術運算符用于形成算術表達式。操作數可以是數字字面量、變量、函數調用或其他表達式。
●運算符按優先級排序。按降序排列為幂、求反、乘法(*、/ 和% 相同)、加法(+ 和-相同)和指派。優先級較高的運算符在優先級較低的運算符之前進行計算。正常優先級可以被括号改變。
● 混合模式操作涉及不同數字資料類型的操作數。它們會産生更具包容性的資料類型的值。
● 輸入後,類型轉換函數可用于将一種類型的值轉換為另一種類型的值。
● 函數調用由函數的名稱及其參數組成。函數被調用時,會對參數進行求值,并将這些值傳遞給函數的代碼進行處理。當函數完成工作時,它可能會将結果值傳回給調用方。
●Python 是一種強類型語言。解釋器檢查表達式中所有操作數的類型,如果給定操作數不符合預期,則停止執行并出錯。
● 子產品是一組資源,例如函數定義。程式員通過從子產品中導入資源來通路它們。
●當計算機無法執行請求的操作時,會出現語義錯誤,例如試圖除以0。帶有語義錯誤的Python 程式停止,并顯示錯誤消息。
● 當一個程式運作到正常終止但産生了不正确的結果時,即存在邏輯錯誤。
2.8 複習題
- 程式員在軟體開發的分析階段會做什麼?
- 用特定的程式設計語言對程式進行編碼
- 編寫解決問題的算法
- 決定程式将做什麼并決定其使用者界面
- 測試程式以驗證其正确性
- 程式員必須用什麼來測試程式?
- 所有可能的合法輸入集
- 所有可能的輸入集
- 一組合法輸入
- 一組合理的合法輸入
- 必須使用什麼來建立多行字元串?
- 一對雙引号
- 一對單引号
- 一對連續三個雙引号
- 嵌入的換行符
- 用來開始行尾注釋的是什麼符号?
- / 符号
- # 符号
- % 符号
- 下列哪些運算符清單按優先級遞減排序?
- +,*,**
- *,/,%
- **,*,+
- 表達式2 ** 3 ** 2 計算得到以下哪一個值?
- 64
- 512
- 8
- 表達式round (23.67) 計算得到以下哪一個值?
- 23
- 23.7
- 24.0
- 假設變量name 的值為33。在執行完name = name * 2 後,name 的值是多少?
- 35
- 33
- 66
- 編寫一個import 語句,隻從數學子產品中導入函數sqrt 和log。
- dir 函數和help 函數的作用是什麼?
2.9 程式設計項目
在接下來的每個項目中,你應該編寫一個包含介紹性文檔字元串的程式。該文檔應該描述程式将做什麼(分析)以及如何做(以僞代碼算法的形式設計程式)。包括所有輸入的适當提示,并适當标記所有輸出。編寫完程式後,一定要用一組合理的合法輸入來測試它。
- 案例研究的所得稅電腦程式輸出一個浮點數字,該數字可能顯示超過兩位的精度。使用round 函數修改程式以在輸出數字中顯示最多兩位精度。
- 如果知道邊的長度,就可以計算立方體的表面積。編寫一個程式,以邊的長度(整數)作為輸入,并列印立方體的表面積作為輸出。
- “五星級複古錄像帶”商店出租VHS 錄音帶和DVD 給那些喜歡購買唱片集的鑒賞家。這家商店以每晚3 美元的價格租賃新視訊,以每晚2 美元的價格租賃老歌。寫一個程式,使公司的職員可以用它來計算客戶視訊租賃的總費用。該程式應該提示使用者輸入每種視訊的數量,并輸出總成本。
- 編寫一個程式,以球體的半徑(浮點數)為輸入,然後輸出球體的直徑、周長、表面積和體積。
- 物體的動量是品質乘以速度。編寫一個程式,接受物體的品質(千克)和速度(米每秒)作為輸入,然後輸出其動量。
- 運動物體的動能由公式KE =(1/2)mv2 給出(其中m 是物體的品質,v 是速度)。修改你在上一題中建立的程式,以便列印出物體的動能和動量。
- 編寫一個程式,計算并列印一年中的分鐘數。
- 光以3×108 米/ 秒的速度傳播。光年是光束在一年内傳播的距離。編寫一個計算和顯示光年值的程式。
- 編寫一個程式,将公裡數作為輸入,并列印相應的海裡數。使用以下近似值:
- 1公裡代表北極和赤道之間距離的1/10000。
- 北極和赤道之間有90度,每度包含60分的弧。
- 1海裡是一個弧的1分。
- 員工的周薪總額等于小時工資乘以正常工作時間的總數加上加班費。加班費等于加班總小時數乘以每小時工資的1.5 倍。編寫一個程式,将小時工資、總正常時數和總加班時數作為輸入,并顯示員工的周薪總額。