圖靈教育 2019-04-09 15:22:39 本文會(huì)通過(guò)一些實(shí)例來(lái)介紹Python 的一些特性,,每個(gè)實(shí)例都會(huì)解決具體的問(wèn)題和難題。
創(chuàng)建有意義的名稱和使用變量如何確保程序易于理解呢,?要編寫(xiě)富有表現(xiàn)力的代碼,,一個(gè)核心要素就是使用有意義的名稱。但什么是有意義的呢,?在本實(shí)例中,,我們將回顧一些創(chuàng)建有意義的Python名稱的通用規(guī)則。 我們還將介紹Python 的一些不同形式的賦值語(yǔ)句,,如用同一條語(yǔ)句為多個(gè)變量賦值,。 一、準(zhǔn)備工作 創(chuàng)建名稱的核心問(wèn)題是:被命名的是什么,? 對(duì)于軟件,,我們需要一個(gè)描述被命名對(duì)象的名稱。顯然,,像x 這樣的名稱不是很有描述性,,它似乎并不指向?qū)嶋H的事物。模糊的非描述性名稱在一些程序設(shè)計(jì)中很常見(jiàn),,令人十分痛苦,。當(dāng)使用它們時(shí),無(wú)助于其他人理解我們的程序,。描述性名稱則一目了然,。 在命名時(shí),區(qū)分解決方案域和問(wèn)題域(真正想要解決的問(wèn)題)也很重要,。解決方案域包括Python,、操作系統(tǒng)和互聯(lián)網(wǎng)的技術(shù)細(xì)節(jié)。不需要深入的解釋,,任何人在閱讀代碼時(shí)都可以看到解決方案,。然而,問(wèn)題域可能因技術(shù)細(xì)節(jié)而變得模糊,。我們的任務(wù)是使問(wèn)題清晰可見(jiàn),,而精心挑選的名稱將對(duì)此有所幫助。 二、實(shí)戰(zhàn)演練 首先看看如何命名,,然后再學(xué)習(xí)如何為對(duì)象分配名稱,。 1. 明智地選擇名稱 在純技術(shù)層面上,Python 名稱必須以字母開(kāi)頭,。它們可以包括任意數(shù)量的字母,、數(shù)字和下劃線。因?yàn)镻ython 3 基于Unicode,,所以字母不限于拉丁字母,。雖然通常使用拉丁字母A~Z,但這不是必須遵循的規(guī)定,。 當(dāng)創(chuàng)建一個(gè)描述性變量時(shí),,我們需要?jiǎng)?chuàng)建既具體又能表達(dá)程序中事物之間關(guān)系的名稱。一種廣泛使用的命名技巧就是創(chuàng)建“從特殊到一般”這種風(fēng)格的長(zhǎng)名稱,。 選擇名稱的步驟如下,。 (1) 名稱的最后一部分是事物的廣義概要。有時(shí)候,,僅此一部分就能滿足命名的需要,,靠上下文提供其余的信息。稍后將介紹一些典型的廣義概要的類別,。 (2) 在應(yīng)用程序或問(wèn)題域周圍使用前綴限定名稱,。 (3) 如有必要,使用更精確和專用的前綴,,以闡明它與其他類,、模塊、包,、函數(shù)和其他對(duì)象的區(qū)別,。對(duì)前綴有疑問(wèn)時(shí),,回想一下域名的工作原理,。例如,mail.google.com 這個(gè)名稱表明了從特殊到一般的三個(gè)級(jí)別,。三個(gè)級(jí)別的命名并不罕見(jiàn),,我們經(jīng)常采用這種命名方法。 (4) 根據(jù)在Python 中的使用方法來(lái)命名,。需要命名的事物有三大類,,如下所示。
如何選擇名稱中廣義類別的那一部分呢,?通用類別取決于討論的是事物還是事物的屬性,。雖然世界上有很多事物,但我們?nèi)匀豢梢詣?chuàng)建一些有用的廣義分類,,例如文檔,、企業(yè)、地點(diǎn),、程序,、產(chǎn)品、過(guò)程,、人,、資產(chǎn)、規(guī)則,、條件,、植物、動(dòng)物、礦物等,。 然后可以用修飾語(yǔ)來(lái)限定這些名稱:
第一個(gè)示例是Document 類,,我們通過(guò)添加一個(gè)前綴對(duì)其進(jìn)行了略微的限定,即StatusDocument,,又通過(guò)將其命名為FinalStatusDocument 來(lái)進(jìn)一步限定,。 第二個(gè)示例是Name 類,我們通過(guò)詳細(xì)說(shuō)明它是一個(gè)ReceivedInventoryItemName 來(lái)對(duì)其進(jìn)行限定,。該示例需要一個(gè)4 個(gè)級(jí)別的名稱來(lái)闡明,。 對(duì)象通常具有特性(property)或者屬性(attribute)。它們應(yīng)當(dāng)是完整名稱的一部分,,可以根據(jù)其表示的信息類型進(jìn)行分解,,如數(shù)量、代碼,、標(biāo)識(shí)符,、名稱、文本,、日期,、時(shí)間、日期時(shí)間,、圖片,、視頻、聲音,、圖形,、值、速率,、百分比,、尺寸等。 命名的思路就是把狹義,、詳細(xì)的描述放在最前面,,把寬泛的信息放在最后:
在第一個(gè)示例中,height 限定了更一般的表示術(shù)語(yǔ)value,,而measured_height_value 做了進(jìn)一步限定,。通過(guò)這個(gè)名稱,,可以思考一下其他與hight 相關(guān)的變體,。類似的思想也適用于weight_value、delivery_date 和location_code,。這些名稱都有一個(gè)或者兩個(gè)限定前綴,。
2. 為對(duì)象分配名稱 Python 沒(méi)有使用靜態(tài)變量定義,。當(dāng)把名稱分配給對(duì)象時(shí),就會(huì)創(chuàng)建變量,。把對(duì)象看作處理過(guò)程的核心非常重要,,變量有點(diǎn)像標(biāo)識(shí)對(duì)象的標(biāo)簽。使用基本賦值語(yǔ)句的方法如下,。 (1) 創(chuàng)建對(duì)象,。在許多示例中,對(duì)象以字面量的形式創(chuàng)建,。我們使用355 或113 作為Python 中整數(shù)對(duì)象的字面量表示,,也可以使用FireBrick 表示字符串,或使用(178,34,34)表示元組,。 (2) 編寫(xiě)如下類型的語(yǔ)句:變量 = 對(duì)象,。例如: >>> circumference_diameter_ratio = 355/113 我們創(chuàng)建了一些對(duì)象并把它們賦值給了變量。第一個(gè)對(duì)象是數(shù)值計(jì)算的結(jié)果,,接下來(lái)的兩個(gè)對(duì)象是簡(jiǎn)單的字面量,。對(duì)象通常由包含函數(shù)或類的表達(dá)式創(chuàng)建。 上面的基本賦值語(yǔ)句并不是唯一的賦值方式,,還可以使用鏈?zhǔn)劫x值的方式,,將一個(gè)對(duì)象分配給多個(gè)變量,例如: >>> target_color_name = first_color_name = 'FireBrick' 上例為同一個(gè)字符串對(duì)象創(chuàng)建了兩個(gè)名稱,??梢酝ㄟ^(guò)檢查Python 使用的內(nèi)部ID 值來(lái)確認(rèn)這兩個(gè)對(duì)象是否為同一個(gè)對(duì)象: >>> id(target_color_name) == id(first_color_name) 結(jié)果表明,,這兩個(gè)對(duì)象的內(nèi)部ID 值是相同的。
隨后介紹數(shù)字和集合時(shí)將會(huì)說(shuō)明結(jié)合運(yùn)算符進(jìn)行賦值的方法。例如: >>> total_count = 0 我們通過(guò)運(yùn)算符進(jìn)行了增量賦值,。total_count + = 5 與total_count = total_count + 5是等價(jià)的,。增量賦值的優(yōu)點(diǎn)在于簡(jiǎn)化了表達(dá)式。 三,、工作原理 本實(shí)例創(chuàng)建名稱的方法遵循如下模式:狹義的,、更具體的限定符放在前面,更寬泛的,、不太特定的類別放在最后,。這種方法遵守用于域名和電子郵件地址的通用約定。 例如,,域名mail.google.com 包括特定的服務(wù),、更通用的企業(yè)和最后的非常通用的域,這遵循了從窄到寬的原則,。 又如,,[email protected] 以具體的用戶名開(kāi)始,然后是更通用的企業(yè),,最后是非常通用的域,。甚至用戶名(PacktPub)也是一個(gè)具有兩部分的名稱,包括限定的企業(yè)名稱(Packt),,以及更廣泛的行業(yè)[Pub,,“Publishing”(出版)的簡(jiǎn)寫(xiě),而不是“Public House”(酒吧)的簡(jiǎn)寫(xiě)],。 賦值語(yǔ)句是為對(duì)象命名的唯一途徑,。 四、補(bǔ)充內(nèi)容 我們將在所有實(shí)例中使用描述性名稱,。
幾乎每個(gè)示例都涉及變量賦值,。變量賦值是有狀態(tài)的面向?qū)ο缶幊痰暮诵摹?/p> 五,、延伸閱讀 描述性命名是一個(gè)正在研討的主題,涉及兩個(gè)方面——語(yǔ)法和語(yǔ)義,。Python 語(yǔ)法的設(shè)想起始于著名的PEP-8(Python Enhancement Proposal number 8),。PEP-8 建議使用CamelCase 和snake_case 命名風(fēng)格。 此外,,務(wù)必進(jìn)行以下操作: >>> import this 這有助于領(lǐng)悟Python 的設(shè)計(jì)哲學(xué),。
使用大整數(shù)和小整數(shù)許多編程語(yǔ)言區(qū)分整數(shù),、字節(jié)和長(zhǎng)整數(shù),,有些編程語(yǔ)言還存在有符號(hào)整數(shù)和無(wú)符號(hào)整數(shù)的區(qū)別。如何將這些概念與Python 聯(lián)系起來(lái)呢,? 答案是“不需要”,。Python 以統(tǒng)一的方式處理所有類型的整數(shù)。對(duì)于Python,,從幾個(gè)字節(jié)到數(shù)百位的巨大數(shù)字,,都是整數(shù)。 一,、準(zhǔn)備工作 假設(shè)我們需要計(jì)算一些非常大的數(shù)字,,例如,,計(jì)算一副52 張的撲克牌的排列數(shù),。52! = 52 × 51×50 × … × 2 × 1,這是一個(gè)非常大的數(shù)字,??梢栽赑ython 中實(shí)現(xiàn)這個(gè)運(yùn)算嗎,? 二、實(shí)戰(zhàn)演練 別擔(dān)心,!Python 表現(xiàn)得好像有一個(gè)通用的整數(shù)類型,,涵蓋了所有整數(shù),從幾個(gè)字節(jié)到填滿所有內(nèi)存的整數(shù),。正確使用整數(shù)的步驟如下,。 (1) 寫(xiě)下你需要的數(shù)字,比如一些小數(shù)字:355,,113,。實(shí)際上,數(shù)字的大小沒(méi)有上限,。 (2) 創(chuàng)建一個(gè)非常小的值——單個(gè)字節(jié),,如下所示: >>> 2 或者使用十六進(jìn)制: >>> 0xff 后面的實(shí)例中將討論只含有一個(gè)值的字節(jié)序列: >>> b'\xfe' 嚴(yán)格說(shuō)來(lái),這不是一個(gè)整數(shù),。它有一個(gè)前綴b',,這表明它是一個(gè)一字節(jié)序列(1-byte sequence),。 (3) 通過(guò)計(jì)算創(chuàng)建一個(gè)很大的數(shù)字。例如: >>> 2 ** 2048 該數(shù)字有617 個(gè)數(shù)位,,這里并沒(méi)有完全顯示,。 三、工作原理 Python 內(nèi)部使用兩種數(shù)字,,兩者之間的轉(zhuǎn)換是無(wú)縫且自動(dòng)的,。 對(duì)于較小的數(shù)字,Python 通常使用4 字節(jié)或8 字節(jié)的整數(shù)值,。細(xì)節(jié)隱藏在CPython 的內(nèi)核中,,并依賴于構(gòu)建Python 的C 編譯器。 對(duì)于超出sys.maxsize 的較大數(shù)字,,Python 將其切換到大整數(shù)——數(shù)字(digit)序列,。在這種情況下,一位數(shù)字通常意味著30 位(bit)的值,。 一副52張的撲克牌有多少種排列方法,?答案是52! ≈ 8 ×10^67。我們將使用math 模塊的factorial函數(shù)計(jì)算這個(gè)大整數(shù),,如下所示: >>> import math 這些巨大的數(shù)字工作得非常完美,! 計(jì)算52! 的第一部分(從52 × 51 × 50 × …一直到約42)可以完全使用較小的整數(shù)來(lái)執(zhí)行。在此之后,,其余的計(jì)算必須切換到大整數(shù),。我們看不到切換過(guò)程,只能看到結(jié)果,。 通過(guò)下面的示例可以了解整數(shù)內(nèi)部的一些細(xì)節(jié),。 >>> import sys sys.maxsize 的值是小整數(shù)中的最大值。我們通過(guò)計(jì)算以2 為底的對(duì)數(shù)來(lái)說(shuō)明這個(gè)數(shù)字需要多 少位,。 通過(guò)計(jì)算可知,,Python 使用63 位值來(lái)表示小整數(shù)。小整數(shù)的范圍是從-2^64 到2^63-1,。在此范圍之外,,使用大整數(shù)。 通過(guò)sys.int_info 的值可知,,大整數(shù)是使用30 位的數(shù)字序列,,每個(gè)數(shù)字占用4 字節(jié)。 像52! 這樣比較大的值,,由8 個(gè)上述30 位的數(shù)字組成,。一個(gè)數(shù)字需要30 位來(lái)表示可能有些令人困惑。以用10 個(gè)符號(hào)表示十進(jìn)制(base 10)的數(shù)字為例,,我們需要2**30 個(gè)不同的符號(hào)來(lái)表示這些大數(shù)字的每位數(shù),。 涉及多個(gè)大整數(shù)值的計(jì)算可能會(huì)消耗相當(dāng)大的內(nèi)存空間,。小數(shù)字怎么辦呢? Python 如何跟蹤大量的小數(shù)字,,如1 和0,? 對(duì)于常用的數(shù)字(-5 到256),Python 實(shí)際上創(chuàng)建了一個(gè)私有的對(duì)象池來(lái)優(yōu)化內(nèi)存管理,。你可以在檢查整數(shù)對(duì)象的id()值時(shí)得到驗(yàn)證,。 >>> id(1) 我們顯示了整數(shù)1 和整數(shù)2 的內(nèi)部id,。當(dāng)計(jì)算a 的值時(shí),,結(jié)果對(duì)象與對(duì)象池中的整數(shù)2 對(duì)象是同一個(gè)對(duì)象。 當(dāng)你練習(xí)這個(gè)示例時(shí),,id()值可能跟示例不同,。但是,在每次使用值2 時(shí),,將使用相同的對(duì)象,。在我的筆記本電腦上,對(duì)象2 的id 等于4297537984,。這種機(jī)制避免了在內(nèi)存里大量存放對(duì)象2 的副本,。 這里有個(gè)小技巧,可以看出一個(gè)數(shù)字到底有多大,。 >>> len(str(2 ** 2048)) 通過(guò)一個(gè)計(jì)算得到的數(shù)字創(chuàng)建一個(gè)字符串,,然后查詢字符串的長(zhǎng)度。結(jié)果表明,,這個(gè)數(shù)字有617個(gè)數(shù)位,。 四、補(bǔ)充知識(shí) Python 提供了一組豐富的算術(shù)運(yùn)算符:+,、- ,、*、/,、//,、%和**。/和//用于除法,,**將執(zhí)行冪運(yùn)算,。 對(duì)于位處理,還有其他一些運(yùn)算符,,比如&,、^、|,、<<和>>,。這些運(yùn)算符在整數(shù)的內(nèi)部二進(jìn)制表示上逐位操作,。它們分別計(jì)算二進(jìn)制與、二進(jìn)制異或,、二進(jìn)制或,、左移和右移。 雖然這些運(yùn)算符也同樣適用于大整數(shù),,但是逐位操作對(duì)于大整數(shù)來(lái)說(shuō)并沒(méi)有實(shí)際意義,。一些二進(jìn)制文件和網(wǎng)絡(luò)協(xié)議會(huì)要查看數(shù)據(jù)的單個(gè)字節(jié)中的位。 可以通過(guò)bin()函數(shù)查看應(yīng)用這些運(yùn)算符的運(yùn)行結(jié)果,。示例如下: >>> xor = 0b0011 ^ 0b0101 先使用0b0011 和0b0101 作為兩個(gè)位串,。這有助于準(zhǔn)確說(shuō)明數(shù)字的二進(jìn)制表示。然后將異或(^)運(yùn)算符應(yīng)用于這兩個(gè)位序列,。最后使用bin()函數(shù)查看位串形式的結(jié)果,。可以通過(guò)結(jié)果仔細(xì)觀察各個(gè)位,,了解操作符的實(shí)際功能,。 可以把一個(gè)字節(jié)分解為若干部分,。假設(shè)我們要將最左邊的2 個(gè)位與其他6 個(gè)位分開(kāi),,其中一種方法是使用位操作(bit-fiddling)表達(dá)式,例如: >>> composite_byte = 0b01101100 這里先定義了一個(gè)composite_byte,,其中最高有效的2 位為01,,最低有效的6 位為101100。再使用>>移位運(yùn)算符將composite_byte 的值右移6 個(gè)位置,,去除最低有效位并保留2 個(gè)最高有效位,。然后使用&運(yùn)算符和掩碼來(lái)進(jìn)行操作。掩碼中值為1 的位,,在結(jié)果中保留對(duì)應(yīng)位置的值,;掩碼中值為0 的位,結(jié)果中對(duì)應(yīng)位置的值被設(shè)置為0,。 五,、延伸閱讀 關(guān)于整數(shù)操作的詳細(xì)信息,請(qǐng)參閱https://www./dev/peps/pep-0237/,。 在浮點(diǎn)數(shù),、小數(shù)和分?jǐn)?shù)之間選擇Python 提供了多種處理有理數(shù)和無(wú)理數(shù)近似值的方法。3 種基本選擇如下: ? 浮點(diǎn)數(shù) ? 小數(shù) ? 分?jǐn)?shù) 有這么多種選擇,,那么怎樣選擇才合適呢,? 一、準(zhǔn)備工作 確定我們的核心數(shù)學(xué)期望值很重要。如果不確定已擁有的數(shù)據(jù)類型或者想要得到的結(jié)果,,真的不應(yīng)該開(kāi)始編碼,。我們需要退一步,用鉛筆和紙來(lái)演算一下,。 除了整數(shù),,在數(shù)學(xué)中涉及的數(shù)字還有3 種。 (1) 貨幣:如美元,、美分或歐元,。貨幣通常具有固定的小數(shù)位數(shù)。另外還有很多舍入規(guī)則,,例如,,可以用這些規(guī)則確定 $2.95 的7.25% 是多少美分。
(2) 有理數(shù)或分?jǐn)?shù):使用美制單位的英尺和英寸,,或在烹飪中使用杯和盎司進(jìn)行測(cè)量時(shí),,經(jīng)常需要使用分?jǐn)?shù),。把一個(gè)8 人量的食譜縮減為5 人量時(shí),,要用5/8 作為縮放因子進(jìn)行分?jǐn)?shù)運(yùn)算。如何將這種方法應(yīng)用到2/3 杯米,,并得到適用于廚房量具的測(cè)量值呢,? (3) 無(wú)理數(shù):包括所有其他類型的計(jì)算。必須注意,,數(shù)字計(jì)算機(jī)只能逼近這些無(wú)理數(shù),,而我們偶爾會(huì)看到近似值的一些奇怪現(xiàn)象。浮點(diǎn)近似值運(yùn)算非???,但有時(shí)會(huì)出現(xiàn)截?cái)鄦?wèn)題。 當(dāng)計(jì)算涉及前兩種數(shù)字時(shí),,應(yīng)當(dāng)避免使用浮點(diǎn)數(shù),。 二、實(shí)戰(zhàn)演練 本實(shí)例將分別討論這3 種數(shù)字,。首先討論貨幣值計(jì)算,。然后討論有理數(shù)計(jì)算,以及無(wú)理數(shù)或浮點(diǎn)數(shù)計(jì)算,。最后討論這些類型之間的顯式轉(zhuǎn)換,。 1. 貨幣值計(jì)算 在處理貨幣值時(shí),應(yīng)當(dāng)堅(jiān)持使用decimal 模塊,。如果使用Python 內(nèi)置的浮點(diǎn)數(shù),,將會(huì)遇到數(shù)字的舍入和截?cái)鄦?wèn)題。 (1) 為了處理貨幣值,首先從decimal 模塊導(dǎo)入Decimal 類,。 >>> from decimal import Decimal (2) 從字符串或整數(shù)創(chuàng)建Decimal 對(duì)象,。 >>> from decimal import Decimal tax_rate 由兩個(gè)Decimal 對(duì)象構(gòu)建,其中一個(gè)基于字符串,,另一個(gè)基于整數(shù),。我們可以直接使用Decimal('0.0725'),而不顯式地執(zhí)行除法,。 結(jié)果稍微大于$0.21,,因?yàn)槲覀冇?jì)算出了小數(shù)位的全部數(shù)字。 (3) 如果通過(guò)浮點(diǎn)數(shù)創(chuàng)建Decimal 對(duì)象,,那么將得到異常的浮點(diǎn)近似值,。應(yīng)當(dāng)避免混用 Decimal和float。為了舍入到最近的便士(penny),,創(chuàng)建一個(gè)penny 對(duì)象,。 >>> penny = Decimal('0.01') (4) 使用penny 對(duì)象量化數(shù)據(jù)。 >>> total_amount = purchase_amount + tax_rate * purchase_amount 上述示例演示了如何使用默認(rèn)的ROUND_HALF_EVEN 舍入規(guī)則,。 舍入規(guī)則有很多種,,Decimal 模塊提供了所有舍入規(guī)則。例如: >>> import decimal 本示例顯示了使用另一種不同的舍入規(guī)則的結(jié)果,。 2. 分?jǐn)?shù)計(jì)算 當(dāng)計(jì)算中含有精確分?jǐn)?shù)值時(shí),,可以使用fractions 模塊。該模塊提供了便于使用的有理數(shù),。處理分?jǐn)?shù)的流程如下,。 (1) 從fractions 模塊導(dǎo)入Fraction 類。 >>> from fractions import Fraction (2) 由字符串,、整數(shù)或整數(shù)對(duì)創(chuàng)建Fraction 對(duì)象,。如果由浮點(diǎn)數(shù)創(chuàng)建Fraction 對(duì)象,可能會(huì)遇到浮點(diǎn)近似值的異?,F(xiàn)象,。當(dāng)分母是2 的冪時(shí),一切正常,。 >>> from fractions import Fraction 我們從字符串2.5 創(chuàng)建了第一個(gè)分?jǐn)?shù),,從浮點(diǎn)計(jì)算5/8 創(chuàng)建了第二個(gè)分?jǐn)?shù)。因?yàn)榉帜甘? 的冪,,所以計(jì)算結(jié)果非常準(zhǔn)確,。 25/16——結(jié)果是一個(gè)看起來(lái)很復(fù)雜的分?jǐn)?shù),那么它的最簡(jiǎn)分?jǐn)?shù)是多少呢,? >>> Fraction(24, 16) 結(jié)果表明,,我們使用大約一杯半的米就可以完成5 人量的食譜。 3. 浮點(diǎn)近似值 Python 的內(nèi)置浮點(diǎn)(float)類型能夠表示各種各樣的值。對(duì)于是否使用浮點(diǎn)值,,選擇的關(guān)鍵在于浮點(diǎn)值通常涉及近似值,。在某些情況下,特別是在做涉及2 的冪的除法時(shí),,結(jié)果是一個(gè)精確的分?jǐn)?shù),。 在其他情況下,浮點(diǎn)值和分?jǐn)?shù)值之間可能存在細(xì)小的差異,,這反映了浮點(diǎn)數(shù)的實(shí)現(xiàn)與無(wú)理數(shù)的數(shù)學(xué)理想之間的差異,。 (1) 要使用浮點(diǎn)數(shù),經(jīng)常需要舍入值來(lái)使它們看起來(lái)合理,。所有浮點(diǎn)計(jì)算的結(jié)果都是近似值,。 >>>(19/155) * (155/19) (2) 上面的值在數(shù)學(xué)上應(yīng)該為1。由于float 使用的是近似值,,所以結(jié)果并不精確,。雖然這個(gè)結(jié)果與1 相差不多,但仍然錯(cuò)了,。當(dāng)進(jìn)行適當(dāng)?shù)纳崛霑r(shí),,這個(gè)值會(huì)更有意義。 >>> answer =(19/155) * (155/19) (3) 認(rèn)識(shí)誤差項(xiàng),。在本例中,,我們知道確切的答案,,所以可以將計(jì)算結(jié)果與已知的正確答案進(jìn)行比較,。下面的示例給出的通用誤差項(xiàng)適用于所有浮點(diǎn)數(shù)。 >>> 1-answer 對(duì)于大多數(shù)浮點(diǎn)誤差,,典型值約為10^16,。Python 有一些聰明的規(guī)則,有時(shí)通過(guò)自動(dòng)舍入隱藏這個(gè)錯(cuò)誤,。但是,,對(duì)于本示例,錯(cuò)誤并沒(méi)有隱藏,。 這是一個(gè)非常重要的推論,。
在浮點(diǎn)數(shù)之間使用精確的==測(cè)試時(shí),,如果近似值相差一個(gè)位,,代碼就會(huì)出現(xiàn)問(wèn)題。 4. 數(shù)字的類型轉(zhuǎn)換 可以使用float()函數(shù)從其他類型的值創(chuàng)建一個(gè)float 值,。例如: >>> float(total_amount) 在第一個(gè)示例中,,我們將Decimal 值轉(zhuǎn)換為float 值。在第二個(gè)示例中,我們將Fraction 值轉(zhuǎn)換為float 值,。 正如剛剛看到的,,我們永遠(yuǎn)不想將float 轉(zhuǎn)換為Decimal 或Fraction: >>> Fraction(19/155) 在第一個(gè)示例中,我們?cè)谡麛?shù)之間進(jìn)行計(jì)算,,創(chuàng)建了一個(gè)具有已知截?cái)鄦?wèn)題的float 值,。當(dāng)我們從截?cái)嗟膄loat 值創(chuàng)建一個(gè)Fraction 時(shí),得到的是一些暴露了截?cái)鄦?wèn)題的數(shù)字,。 類似地,,第二個(gè)示例從float 創(chuàng)建了 Decimal 值。 三,、工作原理 對(duì)于數(shù)字類型,,Python 提供了多種運(yùn)算符:+、-,、*,、/、//,、%和**,。這些運(yùn)算符用于加法、減法,、乘法,、真除法、截?cái)喑?、取模和冪運(yùn)算,。 Python 擅長(zhǎng)各種數(shù)字類型之間的轉(zhuǎn)換。我們可以混合使用整數(shù)(int)和浮點(diǎn)數(shù)(float),,整數(shù)將被轉(zhuǎn)換為浮點(diǎn)數(shù),,以提供最準(zhǔn)確的答案。類似地,,還可以混合使用整數(shù)(int)和分?jǐn)?shù)(Fraction),,結(jié)果將是分?jǐn)?shù)(Fractions)。我們也可以混合使用整數(shù)(int)和小數(shù)( Decimal),。但是,,不能隨便混合使用小數(shù)( Decimal)與浮點(diǎn)數(shù)(float),或小數(shù)( Decimal)與分?jǐn)?shù)(Fraction),,在這樣操作之前,,需要進(jìn)行顯式轉(zhuǎn)換。
我們可以使用普通的十進(jìn)制數(shù)值在Python 中編寫(xiě)如下值: >>> 8.066e + 67 在內(nèi)部使用的實(shí)際值將包含上述十進(jìn)制值的一個(gè)二進(jìn)制近似值,。 該示例(8.066e + 67)中的內(nèi)部值為: >>> 6737037547376141/2 ** 53 * 2 ** 226 分子是一個(gè)大數(shù)字,,6737037547376141;分母總是2^53,。由于分母是固定的,,因而所得到的分?jǐn)?shù)只能有53 位有意義的數(shù)據(jù)。由于53 位之外的位不可用,,因此值可能會(huì)被截?cái)?。這導(dǎo)致了我們的理想化抽象和實(shí)際數(shù)字之間的微小差異。指數(shù)(2^226)需要將分?jǐn)?shù)縮放到適當(dāng)?shù)姆秶?/p> 在數(shù)學(xué)上,,即6737037547376141 * 2^226/2^53,。 可以使用math.frexp()查看數(shù)字的內(nèi)部細(xì)節(jié): >>> import math 結(jié)果的兩個(gè)部分分別稱為尾數(shù)(mantissa)和指數(shù)(exponent)。如果將尾數(shù)乘以2^53,,那么將得到一個(gè)整數(shù),,這個(gè)整數(shù)是二進(jìn)制分?jǐn)?shù)的分子。
與內(nèi)置的float 不同,,F(xiàn)raction 是兩個(gè)整數(shù)值的精確比率。正如前邊所示,,Python 中的整數(shù)可能非常大,。我們可以創(chuàng)建包含具有大量數(shù)位的整數(shù)的比率,并且不受固定分母的限制,。 類似地,,Decimal 值基于非常大的整數(shù)值和用于確定小數(shù)點(diǎn)位置的縮放因子。這些數(shù)字可以是巨大的,,不會(huì)有特殊的表示問(wèn)題,。
四,、補(bǔ)充知識(shí) Python 的math 模塊包含許多用于處理浮點(diǎn)值的專用函數(shù),。該模塊包括了常用的函數(shù),如平方根,、對(duì)數(shù)和各種三角函數(shù),,還包括其他一些函數(shù),如伽瑪函數(shù),、階乘函數(shù)和高斯誤差函數(shù),。 math 模塊也包含了一些可以精確計(jì)算浮點(diǎn)數(shù)的函數(shù)。例如,,math.fsum()函數(shù)將比內(nèi)置sum()函數(shù)更加周密地計(jì)算浮點(diǎn)和,。math.fsum()函數(shù)很少出現(xiàn)近似值問(wèn)題。 還可以使用math.isclose()函數(shù)比較兩個(gè)浮點(diǎn)值是否接近相等: >>> (19/155)*(155/19) == 1.0 該函數(shù)提供了一種正確比較浮點(diǎn)數(shù)的方法,。 Python 還提供了復(fù)數(shù)數(shù)據(jù)類型。復(fù)數(shù)由實(shí)部和虛部組成,。在Python 中,,3.14 + 2.78j 代表復(fù)數(shù) 3.14 + 2.78√-1。Python可以在浮點(diǎn)數(shù)和復(fù)數(shù)之間進(jìn)行輕松的轉(zhuǎn)換,。Python提供了一組常用的復(fù)數(shù)運(yùn)算符。 為了更好地支持復(fù)數(shù),,Python 內(nèi)置了cmath 包。例如,,cmath.sqrt()函數(shù)將返回一個(gè)復(fù)數(shù)值,而不是在求負(fù)數(shù)的平方根時(shí)拋出異常,。示例如下: >>> math.sqrt(-2) 在操作復(fù)數(shù)時(shí),,離不開(kāi)cmath 包,。 五、延伸閱讀 請(qǐng)參閱https://en./wiki/IEEE_floating_point,。 在真除法和floor 除法之間選擇Python 提供了兩種除法運(yùn)算符,。本實(shí)例將介紹這兩種運(yùn)算符以及它們適用的情景,還將介紹Python 除法規(guī)則以及如何對(duì)整數(shù)值進(jìn)行除法運(yùn)算,。 一,、準(zhǔn)備工作 除法運(yùn)算有幾種常見(jiàn)的使用場(chǎng)景。
我們首先需要確定適用哪種情況,然后就知道該使用哪種除法運(yùn)算符了,。 二,、實(shí)戰(zhàn)演練 我們將分別討論這三種情況。首先討論截?cái)嗟膄loor 除法,,然后討論真正的浮點(diǎn)除法,,最后討論分?jǐn)?shù)的除法。 1. floor 除法 在做div-mod 類計(jì)算時(shí),,可以使用floor 除法運(yùn)算符(//)和取模運(yùn)算符(%),。或者也可以使用divmod()函數(shù),。 (1) 將秒數(shù)除以3600 得到小時(shí)數(shù),,模數(shù)或余數(shù)可以分別轉(zhuǎn)換為分鐘數(shù)和秒數(shù)。 >>> total_seconds = 7385 (2) 將步驟(1)剩余的秒數(shù)除以60 得到分鐘數(shù),,余數(shù)是小于60 的秒數(shù),。 >>> minutes = remaining_seconds//60 使用divmod()函數(shù)的示例如下。 (1) 同時(shí)計(jì)算商和余數(shù),。 >>> total_seconds = 7385 (2) 再次計(jì)算商和余數(shù)。 >>> minutes, seconds = divmod(remaining_seconds, 60) 2. 真除法 真值除法計(jì)算的結(jié)果是浮點(diǎn)近似值,。例如,,7386 秒是多少小時(shí),?使用真除法運(yùn)算符進(jìn)行除法運(yùn)算: >>> total_seconds = 7385
這種真除法是Python 3 的特性,。 3. 有理分?jǐn)?shù)計(jì)算 可以用Fraction 對(duì)象和整數(shù)做除法。這將使結(jié)果是一個(gè)數(shù)學(xué)上精確的有理數(shù),。 (1) 創(chuàng)建至少一個(gè)Fraction 值,。 >>> from fractions import Fraction (2) 在計(jì)算中使用Fraction 值,任何整數(shù)都將被提升到分?jǐn)?shù),。 >>> hours = total_seconds / 3600 (3) 如有必要,,將確切分?jǐn)?shù)轉(zhuǎn)換為浮點(diǎn)近似值。 >>> round(float(hours),4) 我們首先為總秒數(shù)創(chuàng)建了一個(gè)Fraction 對(duì)象,。在對(duì)分?jǐn)?shù)做算術(shù)運(yùn)算時(shí),,Python 會(huì)把所有整數(shù)都轉(zhuǎn)換為分?jǐn)?shù),這種轉(zhuǎn)換意味著數(shù)學(xué)運(yùn)算是盡可能精確地完成的,。 三,、工作原理 Python 3 有兩個(gè)除法運(yùn)算符。
>>> 7358.0 // 3600.0 默認(rèn)情況下,,Python 2 只有一個(gè)除法運(yùn)算符,。對(duì)于仍在使用Python 2 的程序員來(lái)說(shuō),可以通過(guò)以下方法使用這些新運(yùn)算符: >>> from __future__ import division 這個(gè)導(dǎo)入將會(huì)引入Python 3 的除法規(guī)則,。 五,、延伸閱讀 請(qǐng)參閱https://www./dev/peps/pep-0238/。 ——本文節(jié)選自《Python經(jīng)典實(shí)例》 解決實(shí)際場(chǎng)景中的具體問(wèn)題,,全面了解Python語(yǔ)言特性 本書(shū)是Python經(jīng)典實(shí)例解析,采用基于實(shí)例的方法編寫(xiě),,每個(gè)實(shí)例都會(huì)解決具體的問(wèn)題和難題,。主要內(nèi)容有:數(shù)字、字符串和元組,,語(yǔ)句與語(yǔ)法,,函數(shù)定義,列表,、集,、字典,用戶輸入和輸出等內(nèi)置數(shù)據(jù)結(jié)構(gòu),,類和對(duì)象,,函數(shù)式和反應(yīng)式編程,Web服務(wù),,等等,。 Python 是全球的開(kāi)發(fā)人員、工程師,、數(shù)據(jù)科學(xué)家和編程愛(ài)好者的首選語(yǔ)言,。它是杰出的腳本語(yǔ)言,可以為你的應(yīng)用程序注入動(dòng)力,,提供出色的速度,、安全性和可擴(kuò)展性。本書(shū)會(huì)通過(guò)一些簡(jiǎn)單的實(shí)例剖析Python,,你可以在特定的情境中深入了解其具體的語(yǔ)言特性,。明確的情境有助于理解語(yǔ)言或標(biāo)準(zhǔn)庫(kù)的特性。 本書(shū)采用基于實(shí)例的方法編寫(xiě),,每個(gè)實(shí)例都會(huì)解決具體的問(wèn)題和難題,。 |
|