久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

你不知道的Python特性,,其實(shí)可以解決很多問(wèn)題,!

 靜幻堂 2019-04-10
圖靈教育 2019-04-09 15:22:39
你不知道的Python特性,其實(shí)可以解決很多問(wèn)題,!

本文會(huì)通過(guò)一些實(shí)例來(lái)介紹Python 的一些特性,,每個(gè)實(shí)例都會(huì)解決具體的問(wèn)題和難題。

  • 創(chuàng)建有意義的名稱和使用變量
  • 使用大整數(shù)和小整數(shù)
  • 在浮點(diǎn)數(shù),、小數(shù)和分?jǐn)?shù)之間選擇
  • 在真除法和floor 除法之間選擇

floor 除法就是向下取整除法,。向上取整除法是ceiling。

創(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)命名,。需要命名的事物有三大類,,如下所示。

  • 類:類的名稱能夠概述類中的所有對(duì)象,。這些名稱通常使用大駝峰命名法(Capitalized-CamelCase),。類名的第一個(gè)字母大寫(xiě),強(qiáng)調(diào)它是一個(gè)類,,而不是類的實(shí)例,。類通常是一個(gè)通用的概念,,很少用于描述有形的事物。
  • 對(duì)象:對(duì)象的名稱通常使用蛇底命名法(snake_case),。名稱全部小寫(xiě),,單詞之間使用多個(gè)下劃線連接。在Python 中,,一切皆是對(duì)象,,包括變量、函數(shù),、模塊,、包、參數(shù),、對(duì)象的屬性,、類的方法等。
  • 腳本和模塊文件:這些文件是Python 看到的真正的操作系統(tǒng)資源,。因此,,文件名應(yīng)遵循Python對(duì)象的約定,使用字母,、下劃線并以 .py 擴(kuò)展名結(jié)尾,。單從技術(shù)上說(shuō),你可天馬行空地設(shè)置文件名,。但是,,不遵循Python 規(guī)則的文件名可能難以用作模塊或包的名稱。

如何選擇名稱中廣義類別的那一部分呢,?通用類別取決于討論的是事物還是事物的屬性,。雖然世界上有很多事物,但我們?nèi)匀豢梢詣?chuàng)建一些有用的廣義分類,,例如文檔,、企業(yè)、地點(diǎn),、程序,、產(chǎn)品、過(guò)程,、人,、資產(chǎn)、規(guī)則,、條件,、植物、動(dòng)物、礦物等,。

然后可以用修飾語(yǔ)來(lái)限定這些名稱:

FinalStatusDocument

ReceivedInventoryItemName

第一個(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ì)的描述放在最前面,,把寬泛的信息放在最后:

measured_height_value

estimated_weight_value

scheduled_delivery_date

location_code

在第一個(gè)示例中,height 限定了更一般的表示術(shù)語(yǔ)value,,而measured_height_value 做了進(jìn)一步限定,。通過(guò)這個(gè)名稱,,可以思考一下其他與hight 相關(guān)的變體,。類似的思想也適用于weight_value、delivery_date 和location_code,。這些名稱都有一個(gè)或者兩個(gè)限定前綴,。

需要避免的情況

切勿使用經(jīng)過(guò)編碼的前綴或后綴去描述詳細(xì)的技術(shù)信息。不要使用f_measured_height_value 這樣的名稱,其中f 可能指的是浮點(diǎn)數(shù),。這種命名方法通常被稱為匈牙利命名法(Hungarian Notation),。像measured_height_value 這樣的變量可以是任意數(shù)字類型,Python 會(huì)做所有必要的轉(zhuǎn)換,。技術(shù)性修飾對(duì)于代碼閱讀者并沒(méi)有多大幫助,,因?yàn)轭愋驼f(shuō)明可能造成誤導(dǎo)甚至錯(cuò)誤。

不要浪費(fèi)太多的精力使名稱看起來(lái)屬于哪個(gè)類別,。不要使用SpadesCardSuit,、ClubsCardSuit 這樣的名稱。Python 有許多種命名空間,,包括包,、模塊和類,命名空間對(duì)象會(huì)把相關(guān)的名稱收集起來(lái),。如果將這些名稱添加到CardSuit 類中,,就可以使用CardSuit.Spades,以類作為命名空間來(lái)區(qū)分其他相似的名稱,。

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
>>> target_color_name = 'FireBrick'
>>> target_color_rgb = (178, 34, 34)

我們創(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)
True

結(jié)果表明,,這兩個(gè)對(duì)象的內(nèi)部ID 值是相同的。

相等測(cè)試使用==,,簡(jiǎn)單賦值使用=,。

隨后介紹數(shù)字和集合時(shí)將會(huì)說(shuō)明結(jié)合運(yùn)算符進(jìn)行賦值的方法。例如:

>>> total_count = 0
>>> total_count += 5
>>> total_count += 6
>>> total_count
11

我們通過(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í)例中使用描述性名稱,。

Tip:沒(méi)有遵循這種模式的現(xiàn)有軟件應(yīng)當(dāng)保持現(xiàn)狀,。一般而言,最好與遺留軟件保持一致,,而不是強(qiáng)加新規(guī)則,,即使新規(guī)則更好。

幾乎每個(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é),。

有關(guān)語(yǔ)義的信息,請(qǐng)參閱遺留的UDEF 和NIEM 命名和設(shè)計(jì)規(guī)則標(biāo)準(zhǔn)(http://www./udefinfo/AboutTheUDEF.pdf),。有關(guān)元數(shù)據(jù)和命名的詳細(xì)信息,,請(qǐng)參閱ISO11179(https://en./wiki/ISO/IEC_11179)。

使用大整數(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
2

或者使用十六進(jìn)制:

>>> 0xff
255

后面的實(shí)例中將討論只含有一個(gè)值的字節(jié)序列:

>>> b'\xfe'
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
323...656

該數(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
>>> math.factorial(52)
80658175170943878571660636856403766975289505440883277824000000000000

這些巨大的數(shù)字工作得非常完美,!

計(jì)算52! 的第一部分(從52 × 51 × 50 × …一直到約42)可以完全使用較小的整數(shù)來(lái)執(zhí)行。在此之后,,其余的計(jì)算必須切換到大整數(shù),。我們看不到切換過(guò)程,只能看到結(jié)果,。

通過(guò)下面的示例可以了解整數(shù)內(nèi)部的一些細(xì)節(jié),。

>>> import sys
>>> import math
>>> math.log(sys.maxsize, 2)
63.0
>>> sys.int_info
sys.int_info(bits_per_digit = 30, sizeof_digit = 4)

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)
4297537952
>>> id(2)
4297537984
>>> a = 1 + 1
>>> id(a)
4297537984

我們顯示了整數(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))
617

通過(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
>>> bin(xor)
'0b110'

先使用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
>>> bottom_6_mask = 0b00111111
>>> bin(composite_byte >> 6)
'0b1'
>>> bin(composite_byte & bottom_6_mask)
'0b101100'

這里先定義了一個(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% 是多少美分。

貨幣的最小單位一般為0.01 元

(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 = Decimal('7.25')/ Decimal(100)
>>> purchase_amount = Decimal('2.95')
>>> tax_rate * purchase_amount
Decimal('0.213875')

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
>>> total_amount.quantize(penny)
Decimal('3.16')

上述示例演示了如何使用默認(rèn)的ROUND_HALF_EVEN 舍入規(guī)則,。

舍入規(guī)則有很多種,,Decimal 模塊提供了所有舍入規(guī)則。例如:

>>> import decimal
>>> total_amount.quantize(penny, decimal.ROUND_UP)
Decimal('3.17')

本示例顯示了使用另一種不同的舍入規(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
>>> sugar_cups = Fraction('2.5')
>>> scale_factor = Fraction(5/8)
>>> sugar_cups * scale_factor
Fraction(25, 16)

我們從字符串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)
Fraction(3, 2)

結(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)
0.9999999999999999

(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)
>>> round(answer, 3)
1.0

(3) 認(rèn)識(shí)誤差項(xiàng),。在本例中,,我們知道確切的答案,,所以可以將計(jì)算結(jié)果與已知的正確答案進(jìn)行比較,。下面的示例給出的通用誤差項(xiàng)適用于所有浮點(diǎn)數(shù)。

>>> 1-answer
1.1102230246251565e-16

對(duì)于大多數(shù)浮點(diǎn)誤差,,典型值約為10^16,。Python 有一些聰明的規(guī)則,有時(shí)通過(guò)自動(dòng)舍入隱藏這個(gè)錯(cuò)誤,。但是,,對(duì)于本示例,錯(cuò)誤并沒(méi)有隱藏,。

這是一個(gè)非常重要的推論,。

Tip:不要比較浮點(diǎn)值是否完全相等。

在浮點(diǎn)數(shù)之間使用精確的==測(cè)試時(shí),,如果近似值相差一個(gè)位,,代碼就會(huì)出現(xiàn)問(wèn)題。

4. 數(shù)字的類型轉(zhuǎn)換

可以使用float()函數(shù)從其他類型的值創(chuàng)建一個(gè)float 值,。例如:

>>> float(total_amount)
3.163875
>>> float(sugar_cups * scale_factor)
1.5625

在第一個(gè)示例中,,我們將Decimal 值轉(zhuǎn)換為float 值。在第二個(gè)示例中,我們將Fraction 值轉(zhuǎn)換為float 值,。

正如剛剛看到的,,我們永遠(yuǎn)不想將float 轉(zhuǎn)換為Decimal 或Fraction:

>>> Fraction(19/155)
Fraction(8832866365939553, 72057594037927936)
>>> Decimal(19/155)
Decimal('0.12258064516129031640279123394066118635237216949462890625')

在第一個(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)換。

必須注意的是,,float 值是真正的近似值,。雖然Python 語(yǔ)法允許將數(shù)字寫(xiě)為小數(shù)值,,但它們?cè)赑ython 內(nèi)部并不是按小數(shù)處理的。

我們可以使用普通的十進(jìn)制數(shù)值在Python 中編寫(xiě)如下值:

>>> 8.066e + 67
8.066e + 67

在內(nèi)部使用的實(shí)際值將包含上述十進(jìn)制值的一個(gè)二進(jìn)制近似值,。

該示例(8.066e + 67)中的內(nèi)部值為:

>>> 6737037547376141/2 ** 53 * 2 ** 226
8.066e + 67

分子是一個(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
>>> math.frexp(8.066E + 67)
(0.7479614202861186, 226)

結(jié)果的兩個(gè)部分分別稱為尾數(shù)(mantissa)和指數(shù)(exponent)。如果將尾數(shù)乘以2^53,,那么將得到一個(gè)整數(shù),,這個(gè)整數(shù)是二進(jìn)制分?jǐn)?shù)的分子。

前面提到的誤差項(xiàng)與該值非常地匹配:10^16 ≈ 2^53,。

與內(nèi)置的float 不同,,F(xiàn)raction 是兩個(gè)整數(shù)值的精確比率。正如前邊所示,,Python 中的整數(shù)可能非常大,。我們可以創(chuàng)建包含具有大量數(shù)位的整數(shù)的比率,并且不受固定分母的限制,。

類似地,,Decimal 值基于非常大的整數(shù)值和用于確定小數(shù)點(diǎn)位置的縮放因子。這些數(shù)字可以是巨大的,,不會(huì)有特殊的表示問(wèn)題,。

為什么要使用浮點(diǎn)數(shù)?原因有兩個(gè)

并不是所有可計(jì)算的數(shù)字都可以表示為分?jǐn)?shù),。這就是數(shù)學(xué)家引入(或者可能是發(fā)現(xiàn))無(wú)理數(shù)的原因。內(nèi)置的float 類型與無(wú)理數(shù)的數(shù)學(xué)抽象非常接近,。例如,,像√2 這樣的值就不能表示為分?jǐn)?shù),。

此外,,浮點(diǎn)值運(yù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
False
>>> math.isclose((19/155)*(155/19), 1)
True

該函數(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)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: math domain error
>>> cmath.sqrt(-2)
1.4142135623730951j

在操作復(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)景。

  • div-mod 對(duì):我們需要兩部分值——商和余數(shù),。當(dāng)對(duì)數(shù)值進(jìn)行數(shù)制轉(zhuǎn)換時(shí),,或者把秒數(shù)轉(zhuǎn)換為小時(shí),、分鐘和秒時(shí),,會(huì)執(zhí)行div-mod 除法,。我們不想要確切的小時(shí)數(shù),只是想要一個(gè)截?cái)嗟男r(shí)數(shù),,余數(shù)轉(zhuǎn)換為分鐘和秒,。
  • 真實(shí)(true)值:典型的浮點(diǎn)值——商的良好近似值。例如,,如果計(jì)算一些測(cè)量數(shù)據(jù)的平均值,,那么我們通常希望結(jié)果是浮點(diǎn)值,即使輸入值都是整數(shù),。
  • 合理的分?jǐn)?shù)值:當(dāng)我們使用英尺,、英寸和杯等美國(guó)單位時(shí),常常需要這種值,。為此,,應(yīng)當(dāng)使用Fraction 類。當(dāng)使用Fraction 對(duì)象時(shí),,總是得到確切的答案,。

我們首先需要確定適用哪種情況,然后就知道該使用哪種除法運(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
>>> hours = total_seconds//3600
>>> remaining_seconds = total_seconds % 3600

(2) 將步驟(1)剩余的秒數(shù)除以60 得到分鐘數(shù),,余數(shù)是小于60 的秒數(shù),。

>>> minutes = remaining_seconds//60
>>> seconds = remaining_seconds % 60
>>> hours, minutes, seconds
(2, 3, 5)

使用divmod()函數(shù)的示例如下。

(1) 同時(shí)計(jì)算商和余數(shù),。

>>> total_seconds = 7385
>>> hours, remaining_seconds = divmod(total_seconds, 3600)

(2) 再次計(jì)算商和余數(shù)。

>>> minutes, seconds = divmod(remaining_seconds, 60)
>>> hours, minutes, seconds
(2, 3, 5)

2. 真除法

真值除法計(jì)算的結(jié)果是浮點(diǎn)近似值,。例如,,7386 秒是多少小時(shí),?使用真除法運(yùn)算符進(jìn)行除法運(yùn)算:

>>> total_seconds = 7385
>>> hours = total_seconds / 3600
>>> round(hours, 4)
2.0514

我們提供了兩個(gè)整數(shù)值,但得到了一個(gè)精確的浮點(diǎn)數(shù)結(jié)果,。與以前使用浮點(diǎn)值的實(shí)例相一致,,我們?nèi)≌私Y(jié)果,以避免出現(xiàn)微小的誤差值,。

這種真除法是Python 3 的特性,。

3. 有理分?jǐn)?shù)計(jì)算

可以用Fraction 對(duì)象和整數(shù)做除法。這將使結(jié)果是一個(gè)數(shù)學(xué)上精確的有理數(shù),。

(1) 創(chuàng)建至少一個(gè)Fraction 值,。

>>> from fractions import Fraction
>>> total_seconds = Fraction(7385)

(2) 在計(jì)算中使用Fraction 值,任何整數(shù)都將被提升到分?jǐn)?shù),。

>>> hours = total_seconds / 3600
>>> hours
Fraction(1477, 720)

(3) 如有必要,,將確切分?jǐn)?shù)轉(zhuǎn)換為浮點(diǎn)近似值。

>>> round(float(hours),4)
2.0514

我們首先為總秒數(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)算符。

  • 真除法運(yùn)算符/總是試圖產(chǎn)生一個(gè)浮點(diǎn)數(shù)結(jié)果,,即使這兩個(gè)操作數(shù)是整數(shù),。從這個(gè)角度來(lái)看,真除法運(yùn)算符是一個(gè)不尋常的運(yùn)算符,。其他所有運(yùn)算符都試圖保留數(shù)據(jù)的類型,。當(dāng)應(yīng)用于整數(shù)時(shí),真除法運(yùn)算會(huì)產(chǎn)生浮點(diǎn)數(shù)結(jié)果,。
  • 截?cái)喑ㄟ\(yùn)算符//總是試圖產(chǎn)生截?cái)嗟慕Y(jié)果,。對(duì)于兩個(gè)整數(shù)操作數(shù),結(jié)果是截?cái)嗌?。?duì)于兩個(gè)浮點(diǎn)數(shù)操作數(shù),,結(jié)果是一個(gè)截?cái)嗟母↑c(diǎn)數(shù)結(jié)果。
>>> 7358.0 // 3600.0
2.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í)例》

你不知道的Python特性,,其實(shí)可以解決很多問(wèn)題,!

解決實(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)題和難題,。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多