數(shù)值類型
本章我們將鏡像更深入的Python語言之旅。在Python中數(shù)據(jù)采用了對(duì)象的形式----無論是Python所提供的內(nèi)置對(duì)象好啰,或是我們使用Python工具以及像C這樣的其他語言所創(chuàng)建的對(duì)象。事實(shí)上而钞,對(duì)象是一切Python程序的基礎(chǔ)仪壮,因?yàn)閷?duì)象是Python程序中的最基本的概念蒲稳,所以對(duì)象也是本書第一個(gè)關(guān)注的焦點(diǎn)瞭郑。
在上一章辜御,我們對(duì)Python的核心對(duì)象類型進(jìn)行了概覽。盡管上一章已經(jīng)介紹了最核心的術(shù)語屈张,但受限于篇幅擒权,并沒有涉及更多的細(xì)節(jié)。本章將對(duì)數(shù)據(jù)類型進(jìn)行更詳盡的學(xué)習(xí)阁谆,以此步長之前略過的細(xì)節(jié)碳抄。
數(shù)值類型基礎(chǔ)知識(shí)
Python中大部分?jǐn)?shù)值類型都是相當(dāng)?shù)湫偷摹K鼈兛梢杂脕碛涗浤愕你y行收支场绿,地球到火星的距離剖效,訪問網(wǎng)站的人數(shù)以及其他任何數(shù)值量。
在Python中,組織并不真的只是一種對(duì)象類型贱鄙,而是一組類似的分類劝贸、Python不僅支持通常的數(shù)字類型,還提供了字面量來直接創(chuàng)建數(shù)字和表達(dá)式以處理數(shù)字逗宁,此外,Python為更高級(jí)的工作提供了很多高級(jí)數(shù)值編程支持和對(duì)象梦湘。完整的Python數(shù)值類型包括:
整數(shù)和浮點(diǎn)數(shù)
復(fù)數(shù)對(duì)象
小數(shù):固定精度對(duì)象
分?jǐn)?shù):有理數(shù)對(duì)象
集合:帶有數(shù)值運(yùn)算的集合體
布爾值:真和假
內(nèi)置函數(shù)和模塊:round瞎颗,math,random等
表達(dá)式捌议;無限制整數(shù)精度哼拔;位運(yùn)算;十六進(jìn)制瓣颅,八進(jìn)制和二進(jìn)制
第三方擴(kuò)展:向量倦逐,庫,可視化宫补,作圖等
數(shù)值字面量
Python提供了整數(shù)以及浮點(diǎn)數(shù)作為基本類型檬姥。Python還允許我們使用十六進(jìn)制,八進(jìn)制和二進(jìn)制怎么量來表示整數(shù)粉怕;提供了一個(gè)復(fù)數(shù)類型健民,并且允許整數(shù)具有無限的精度----只要內(nèi)存空間允許,整數(shù)可以增長任意位數(shù)的數(shù)字贫贝。
字面量? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?解釋
1234秉犹,-456,0,9999999999? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?整數(shù),無大小限制
1.23,1.稚晚,3.14e-10,4E210,4.0e+210? ? ? ? ? ? ? ? ? ? 浮點(diǎn)數(shù)
0o177,0x9ff,0b101010? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Python3.X中的八進(jìn)制崇堵,十六進(jìn)制和二進(jìn)制
3+4j,3.0+4.0j客燕,3J? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?復(fù)數(shù)
set('sadw'),{1,2,3,4}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?集合
Decimal('1.0),Fraction(1,3)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 小數(shù)和分?jǐn)?shù)擴(kuò)展類型
bool(X),True,False? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 布爾類型
一些需要強(qiáng)調(diào)的:
整數(shù)和浮點(diǎn)數(shù)字面量:整數(shù)寫成十進(jìn)制數(shù)字的長鸳劳。浮點(diǎn)數(shù)帶一個(gè)小數(shù)點(diǎn),也可以加上一個(gè)科學(xué)技術(shù)標(biāo)志e或者E幸逆。
Python3.X中的整數(shù):一般整數(shù)和長整數(shù)已經(jīng)合二為一了棍辕。
十六進(jìn)制數(shù)、八進(jìn)制和二進(jìn)制字面量:整數(shù)可以編寫為十進(jìn)制还绘,十六進(jìn)制楚昭,八進(jìn)制,二進(jìn)制形式拍顷、后三者在一些編程領(lǐng)域是常見的抚太。十六進(jìn)制以0X或0X開頭,后面接十六進(jìn)制的數(shù)字0-9和A-F。十六進(jìn)制的數(shù)字編寫成大寫或小寫都可以尿贫。八進(jìn)制數(shù)字字面量以0o或0O開頭电媳,后面節(jié)著數(shù)字0-7組成的數(shù)字串。要注意庆亡!所有這些字面量在程序代碼中都產(chǎn)生一個(gè)整數(shù)對(duì)象匾乓,它們僅僅是特定值的不同語法表示而已。
復(fù)數(shù):Python的復(fù)數(shù)字面量寫成實(shí)部+虛部的寫法又谋,這里虛部都是以J或者j結(jié)尾拼缝。其中,實(shí)部從技術(shù)上講可以省略彰亥,所以虛部可以獨(dú)立于實(shí)部存在咧七。從內(nèi)部來看,復(fù)數(shù)是通過一對(duì)浮點(diǎn)數(shù)來實(shí)現(xiàn)的任斋,但是對(duì)復(fù)數(shù)的所有數(shù)字運(yùn)算都會(huì)按照復(fù)數(shù)的運(yùn)算法則進(jìn)行继阻。
編寫其他的數(shù)值類型:你需要導(dǎo)入某些模塊并調(diào)用其函數(shù)來創(chuàng)建一些數(shù)值類型(如小數(shù)和分?jǐn)?shù)),其他的一些擁有它們自己的字面量語法(如集合)废酷。
內(nèi)置數(shù)值工具
Python提供了一系列處理數(shù)字對(duì)象的工具:
表達(dá)式運(yùn)算符? +瘟檩、-、*锦积、/芒帕、>>、**丰介、&等
內(nèi)置數(shù)學(xué)函數(shù)pow背蟆、abs、round哮幢、int带膀、hex、bin橙垢、等
工具模塊 random垛叨、math等
隨著深入的學(xué)習(xí)這些我們都會(huì)見到。
盡管數(shù)字主要還是通過表達(dá)式柜某,內(nèi)置函數(shù)和模塊處理嗽元,但是它們?nèi)缃褚矒碛性S多專門用于類型的方法。這些內(nèi)容將在本章中介紹喂击。例如剂癌,浮點(diǎn)數(shù)擁有一個(gè)as_integer_ratio方法,它對(duì)分?jǐn)?shù)數(shù)值類型很有用翰绊。
Python表達(dá)式運(yùn)算符
表達(dá)式是處理數(shù)字的最基本工具佩谷,表達(dá)式的定義是:數(shù)字(或其他對(duì)象)與運(yùn)算符相結(jié)合旁壮,并被Python在執(zhí)行時(shí)計(jì)算為一個(gè)值。在Python中你可以使用一般的數(shù)學(xué)記號(hào)與運(yùn)算符號(hào)來編寫表達(dá)式谐檀。例如抡谐,讓兩個(gè)數(shù)字X和Y相加就可以寫成X+Y
下面列舉我所知Python中所有的運(yùn)算符表達(dá)式
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 這個(gè)是表5-1
運(yùn)算符? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?描述
yield x? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 生成器函數(shù)send協(xié)議
lambda args:expression? ? ? ? ? ? ? ? ? ? 創(chuàng)建匿名函數(shù)
x if y else z? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?三元選擇表達(dá)式
x or y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?邏輯或
x and y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?邏輯與
not x? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?邏輯非
x in y,x not in y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?成員關(guān)系
x is y,x is not y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 對(duì)象同一性測(cè)試
x<y,x<=y,x>y,x>=y? ? ? ? ? ? ? ? ? ? ? ? ? ? ?大小比較,集合的子集和超集
x == y,x != y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 值等價(jià)性運(yùn)算符
x|y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 按位或桐猬,集合合并
x^y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?按位異或麦撵,集合對(duì)稱差集
x&y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 按位與,集合交換
x<<y,x>>y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 將x左移或右移y位
x + y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?加法溃肪,拼接
x - y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?減法厦坛,集合差集
x*y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 乘法,重復(fù)
x%y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?求余數(shù)乍惊,格式化
x / y,x//y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?真除法,向下取整除法
-x,+x? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 取負(fù)放仗,取正
~x? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 按位非(取反碼)
x ** y? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?冪運(yùn)算(指數(shù))
x[i]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 索引(映射润绎,序列等)
x[i:j:k]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?分片,切片
x(...)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?調(diào)用(函數(shù)诞挨,類莉撇,方法,其他可調(diào)用對(duì)象)
x.attr? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?屬性引用
(....)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 元組惶傻,表達(dá)式棍郎,生成器表達(dá)式
[...]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?列表,列表推導(dǎo)
{...}? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?字典银室,集合涂佃,集合與字典推導(dǎo)
書上即介紹2.X又涉及3.X。因此這里做出一些講解蜈敢。
Python3.X中x <> y的格式被移除了辜荠。
Python3.X中,X/Y表達(dá)式會(huì)執(zhí)行真除法(保留了商的小數(shù)部分)
[...]語法同時(shí)用于列表字面量抓狭,列表推導(dǎo)表達(dá)式伯病。列表推導(dǎo)表達(dá)式會(huì)執(zhí)行隱式的循環(huán)并把表達(dá)式的結(jié)果收集到一個(gè)新列表中。
(...)語法用于元組和表達(dá)式分組否过,以及生成器表達(dá)式午笛。生成器是一種能夠按照需求產(chǎn)出結(jié)果的列表推導(dǎo),而不是一次性創(chuàng)建完整的結(jié)果列表苗桂。
{...}語法用于字典字面量药磺,并且在Python3.X和2.X可以表示集合字面量以及字典和集合推導(dǎo)。
yield和三元if/else選擇表達(dá)式在Python2.5以及之后的版本可用誉察。yeild會(huì)在生成器中返回send(...)參數(shù)与涡;三元if/esle選擇表達(dá)式是一個(gè)多行if語句的簡(jiǎn)化形式。如果yield不是單獨(dú)位于第一條賦值語句的郵編,需要用圓括號(hào)
比較運(yùn)算符可用鏈?zhǔn)绞褂茫簒<y<z的結(jié)果與x<y and y<x相同驼卖。
分片表達(dá)式X[I:J:K等同于用一個(gè)分片對(duì)象進(jìn)行索引
在Python3.X中氨肌,比較非數(shù)字的混合類型的相對(duì)大小是不允許的。
在Python3.X中酌畜,字典的相對(duì)大小比較也不再支持(盡管支持等價(jià)性測(cè)試):比較sorted(aDict.items())是一種可能的替代
混合運(yùn)算遵循運(yùn)算符優(yōu)先級(jí)
對(duì)于復(fù)雜的表達(dá)式怎囚,例如 A *B + C * D 。Python是怎么知道先進(jìn)行哪個(gè)操作呢桥胞?這個(gè)問題的答案就在于對(duì)運(yùn)算符優(yōu)先級(jí)恳守。當(dāng)編寫含有一個(gè)運(yùn)算符以上的表達(dá)式時(shí),Python將按照所謂的優(yōu)先級(jí)法則對(duì)表達(dá)式進(jìn)行分組贩虾,這個(gè)分組決定了表達(dá)式中各部分的計(jì)算順序催烘,
在表5-1中,運(yùn)算符從上到下優(yōu)先級(jí)逐漸增高缎罢,也就是說越下面的表達(dá)式‘綁定的越緊’
表5-2中位于同一行的表達(dá)式在分組的時(shí)候通常按照從左到右組合(除了冪運(yùn)算伊群,它是從右向左組合的,還有比較運(yùn)算策精,是從左到右連接的)
如計(jì)算X + Y * Z 舰始。Python首先計(jì)算乘法Y * Z,然后鍵結(jié)果與X相加
括號(hào)分組子表達(dá)式
如果用圓括號(hào)將表達(dá)式各部分進(jìn)行分組,就可以不必記憶優(yōu)先級(jí)的事情了咽袜,當(dāng)你但子表達(dá)式括在圓括號(hào)中時(shí)丸卷,就會(huì)超越Python的優(yōu)先級(jí)規(guī)則。Python總會(huì)先計(jì)算圓括號(hào)中的表達(dá)式么然后將結(jié)果用于整個(gè)表達(dá)式中。
例如,表達(dá)式X +Y * Z 寫成下邊兩個(gè)表達(dá)式中的任意一種宾肺,從而強(qiáng)制Python按照你想要的順序計(jì)算表達(dá)式:
(X + Y) * Z? ? ? ? ? ? ? ? ? ? ? ? ? ? X + (Y * Z)
在第一種情況下,“+”首先用作與X和Y。在第二種情況下僧鲁,首先使用“*”(即使這里沒有括號(hào)也會(huì)這樣)。一般來說偶惠,在一個(gè)大型表達(dá)式中添加括號(hào)是個(gè)很好的做法绑改,因?yàn)樗粌H能夠按照你想要的循序進(jìn)行計(jì)算厘线,也增加了程序的可讀性识腿。
混合類型向上轉(zhuǎn)換
除了在表達(dá)式中混個(gè)運(yùn)算符外,你也可以混合數(shù)值類型造壮。例如把一個(gè)整數(shù)和浮點(diǎn)數(shù)相加:
40 + 3.14
但這將會(huì)引發(fā)一個(gè)問題渡讼,混合后的結(jié)果是什么類型?
在混合類型的表達(dá)式中耳璧,Python實(shí)現(xiàn)將被操作的對(duì)象轉(zhuǎn)換為最復(fù)雜的操作數(shù)的類型成箫,然后在對(duì)相同類型的操作數(shù)進(jìn)行數(shù)學(xué)運(yùn)算。
Python是這樣劃分?jǐn)?shù)值類型的復(fù)雜度的:整數(shù)比浮點(diǎn)數(shù)簡(jiǎn)單旨枯,浮點(diǎn)數(shù)比復(fù)數(shù)簡(jiǎn)單蹬昌。因此當(dāng)一個(gè)整數(shù)與浮點(diǎn)數(shù)混合時(shí),整數(shù)會(huì)先升級(jí)為浮點(diǎn)數(shù)的值攀隔,之后通過浮點(diǎn)數(shù)的有運(yùn)算法則得到浮點(diǎn)數(shù)的結(jié)果凳厢。
同理,任意混合類型的表達(dá)式,其中一個(gè)操作數(shù)是更為復(fù)雜的數(shù)字败潦,就會(huì)導(dǎo)致其他的湊整數(shù)升級(jí)為一個(gè)復(fù)制的數(shù)字沟饥,使表達(dá)式獲得一個(gè)復(fù)雜的結(jié)果砾脑。
你可以通過手動(dòng)調(diào)用內(nèi)置函數(shù)來強(qiáng)制轉(zhuǎn)換類型
然而,你通常不需要這樣做勃蜘,因?yàn)镻ython在表達(dá)式中會(huì)自動(dòng)升級(jí)為更復(fù)雜的類型匀归,其結(jié)果往往就是你想要的仿便。
再者,要記住所有這些混合類型的轉(zhuǎn)換僅適用于數(shù)值類型。一般來說,Python不會(huì)在其他的類型之間進(jìn)行轉(zhuǎn)換。例如,一個(gè)字符串和一個(gè)整數(shù)相加就會(huì)產(chǎn)生錯(cuò)誤。
預(yù)習(xí):運(yùn)算符重載和多態(tài)
盡管我們目前把注意力集中在內(nèi)置數(shù)字上,但是所有的Python運(yùn)算符都可以被Python的類或C擴(kuò)展類型重載(即實(shí)現(xiàn))友驮,從而能用于你自己創(chuàng)建的對(duì)象。例如裸扶,你之后將看到用類編寫的對(duì)象代碼也可以使用x+y表達(dá)式做加法或者拼接谓罗,以及使用x[i]表達(dá)式進(jìn)行索引等。
再者艺挪,Python本書也自動(dòng)重載了某些運(yùn)算符妙蔗,這樣它能夠根據(jù)所處理的內(nèi)置對(duì)象的類型執(zhí)行不同的操作梳凛。例如叛溢,“+”運(yùn)算符是用于數(shù)字做加法支示,而用于字符串或列表這樣的序列對(duì)象是做拼接運(yùn)算败晴。實(shí)際上闲擦,“+"用在你自己定義的類的對(duì)象上時(shí),可以進(jìn)行你想要的任意操作。
如前一章所述蜕琴,這種特性通常稱為多態(tài)雏搂。多態(tài)指的是:操作的意義由操作對(duì)象來決定矛市。我們將會(huì)在第16章重訪并深入探索這個(gè)概念,因?yàn)樵谀抢锏纳舷挛闹校梢钥闯龆鄳B(tài)的更多明顯的特征。
數(shù)字的實(shí)際應(yīng)用
讓我們向代碼金發(fā)!也許理解數(shù)值對(duì)象和表達(dá)式最好的方式,就是看看它們?cè)趯?shí)際中的應(yīng)用秀存。因此在掌握基礎(chǔ)知識(shí)后,讓我們打開交互命令行令宿,來實(shí)驗(yàn)一些簡(jiǎn)單的說明性運(yùn)算癞松。
變量與基礎(chǔ)表達(dá)式
首先枫甲,讓我們練習(xí)一下基本的數(shù)學(xué)運(yùn)算凳枝。在下面的交互中,首先把兩個(gè)變量賦值為整數(shù)智什,以便在更大的表達(dá)式中使用他們共虑。變量就是每次疾党,可以用于記錄程序中的信息香罐。
變量在第一次賦值時(shí)被創(chuàng)建寸宏。
變量在表達(dá)式中使用時(shí),會(huì)替換成它們的值搅吁。
變量在表達(dá)式中使用之前,編寫已被賦值蛉威。
變量引用對(duì)象,而且從不需要事先說明废恋。
換句話說,喜愛喵喵賦值語句會(huì)自動(dòng)創(chuàng)建變量a和b
這里要插入性的講一個(gè)東西:注釋半开。注釋是為代碼編寫人類可讀的文檔的方式,也屬于編程中一個(gè)重要的部分炭序。簡(jiǎn)單來說嫌佑,就是記錄一些話語在代碼中,但不會(huì)改變代碼畸颅,注釋不會(huì)被執(zhí)行〖崴祝可以幫助你更好的理解代碼,如何幫助取決于如何寫注釋。注釋不是程序边涕,就是一些話,隨便說美浦,隨便嘮。這里先說一個(gè)最簡(jiǎn)單的晦嵌,#踪古,在井號(hào)后面的語句不會(huì)被執(zhí)行。
由于現(xiàn)在還處于交互命令行模式下参滴,井號(hào)這種單行注釋足夠我們現(xiàn)在使用了。以后會(huì)講解一個(gè)多行字符串脆诉。還有一點(diǎn)促脉,網(wǎng)上有些段子講注釋的孽糖,一般常見的是//? ?铸题,要記住饮六,這個(gè)//不是Python的注釋,放這不好使殖属。
回到正題,目前嵌灰,a和b的值是3和4延曙,當(dāng)變量被用在表達(dá)式中俱诸,它們就會(huì)自動(dòng)被替換成它們的值寓调,而當(dāng)我們?cè)诮换ツJ较逻\(yùn)行時(shí)重窟,表達(dá)式的結(jié)果會(huì)在計(jì)算完成后立即顯示出來厅翔。
從技術(shù)上來講刀闷,這里顯示的結(jié)果是包含兩個(gè)值的元組,因?yàn)樵谳斎胄猩习藘蓚€(gè)逗號(hào)分隔的表達(dá)式筒扒,這就是為什么顯示結(jié)果被包含在括號(hào)內(nèi)的原因村缸。要注意,表達(dá)式能夠準(zhǔn)確工作是因?yàn)閍和b已經(jīng)被提前賦值寿弱,如果選擇一個(gè)還未賦值的變量
你不需要在Python中提前聲明變量,但變量在使用之前必須至少被賦值一次坦仍,實(shí)際上,這意味著你在累加計(jì)算器之前必須先將它們賦值為0唠椭,在列表尾部添加元素之前必須先初始化一個(gè)空列表。
下面是兩個(gè)稍長一些的表達(dá)式雏婶,它們展示了運(yùn)算符分組以及類型轉(zhuǎn)化捎泻。
在第一個(gè)表達(dá)式中支鸡,因?yàn)闆]有括號(hào),所以Python會(huì)自動(dòng)根據(jù)運(yùn)算符有限級(jí)將各部分分組。要注意县貌,在第一個(gè)表達(dá)式中所有的數(shù)字都是除法捐韩,但是得到的結(jié)果是5.0,裁良。因?yàn)樵赑ython3.X中“/”會(huì)執(zhí)行真除法签财,如果想要得到5蕊苗,應(yīng)該使用//捡需。
在第二個(gè)表達(dá)式中,括號(hào)用在“+”的周圍,強(qiáng)制Python先計(jì)算+稠肘。并且通過增加小數(shù)點(diǎn)讓其中應(yīng)該操作對(duì)象是浮點(diǎn)數(shù)2.0.因此是混合類型,Python在進(jìn)行+之前會(huì)先將a引用的整數(shù)變成浮點(diǎn)數(shù)的值瓮增。
數(shù)值的顯示格式
這是對(duì)于一些早期版本的問題袜爪。
對(duì)于這個(gè)例子如果你的版本在2.7之前颁股,Python3.0或更早的版本可能會(huì)看到不同的結(jié)果甘有。
可能是0.8000000000000000000004。這個(gè)奇怪的結(jié)果背后真正的原因是浮點(diǎn)數(shù)的硬件限制,以及浮點(diǎn)數(shù)無法精確的表示一些值间影。因?yàn)橛?jì)算機(jī)體系結(jié)構(gòu)不在本書的討論范圍魂贬,所以我們只能說你的計(jì)算機(jī)的浮點(diǎn)數(shù)硬件已經(jīng)盡力了,而硬件和Python在這里都沒有問題键科。
實(shí)際上勋颖,這真的只是一個(gè)顯示問題----交互式命令行下的自動(dòng)結(jié)果顯示會(huì)比這里的print語句顯示更多的數(shù)字位數(shù)酸钦,是因?yàn)樗褂昧瞬煌乃惴āK鼈冊(cè)趦?nèi)存中對(duì)應(yīng)的是相同的數(shù)字欢伏。如果你不想看到所有的位數(shù),那就使用print葛假。從版本2.7和3.1起抱究,Python的浮點(diǎn)數(shù)顯示邏輯嘗試變得更加智能,它經(jīng)常能夠顯示較少的位數(shù)妈候,但偶爾會(huì)更多。
str和repr顯示格式
從技術(shù)上講墓毒,默認(rèn)的交互式命令行顯示和print的區(qū)別,相當(dāng)于內(nèi)置repr和str函數(shù)的區(qū)別
str和repr都會(huì)把任意對(duì)象轉(zhuǎn)換為對(duì)應(yīng)的字符串表示:repr(以默認(rèn)的交互式命令行顯示)會(huì)產(chǎn)生看起來像代碼的結(jié)果主胧。str(和prin操作)轉(zhuǎn)換為一種通常對(duì)用戶更友好的格式焙格。對(duì)象同時(shí)擁有這兩種方式:str用于一般用途,repr帶有額外的細(xì)節(jié)冬阳,我們?cè)趯W(xué)完字符串以及類中的運(yùn)算符重載后,會(huì)重新認(rèn)識(shí)這一概念氯窍。
除了為任意對(duì)象提供可打印的字符串,str內(nèi)置函數(shù)也是字符串?dāng)?shù)據(jù)類型的名稱熊楼,而且在python3.X中可以傳入一個(gè)編碼名稱犬耻,從一個(gè)字節(jié)串中解碼一個(gè)Unicode字符串渡蜻。
這也是第四章見過的bytes。decode方法的替代方案学密。
普通比較與鏈?zhǔn)奖容^
數(shù)字可以進(jìn)行比較彤守,一般的比較的能夠像我們所期待的那用用于數(shù)字,它們會(huì)比較操作數(shù)的相對(duì)大小筝蚕,并且返回一個(gè)布爾類型的結(jié)果,我們一般會(huì)對(duì)這個(gè)布爾類型進(jìn)行測(cè)試燎含,并以此決定在更大的語句和程序中接下來要執(zhí)行的內(nèi)容。
再次注意數(shù)值表達(dá)式中是如何允許混合類型赴魁,在上面第二個(gè)表達(dá)式中,Python比較了更為復(fù)雜的浮點(diǎn)類型的值潘拱。
Python還允許我們把多個(gè)比較鏈接起來執(zhí)行范圍測(cè)試、鏈?zhǔn)奖容^是更大的布爾表達(dá)式的簡(jiǎn)寫禽最,簡(jiǎn)而言之,Python允許將大小比較測(cè)試鏈接起來懦趋,形成如范圍測(cè)試的連續(xù)比較走贪。
獲得false的結(jié)果是一樣的坠狡,并且允許任意的鏈?zhǔn)介L度
你可以在鏈?zhǔn)綔y(cè)試中使用其他的比較,不過最終的表達(dá)式可能會(huì)很晦澀凯亮,除非你使用Python的方式來計(jì)算。
Python不會(huì)把表達(dá)式1 == 2 的False的結(jié)果與3進(jìn)行比較,這樣做的話啃沪,從技術(shù)上的含義與0 < 3相同,即得到True(True和False只不過是定制化的1和0)
在繼續(xù)學(xué)習(xí)之前在說一點(diǎn)追驴,除了鏈接,數(shù)值的比較是基于相對(duì)大小的糯崎,這很容易理解年栓。不過纸兔。浮點(diǎn)數(shù)不會(huì)總是按照你的預(yù)期工作,而且有時(shí)你要借助其他處理才能進(jìn)行有意義的比較洲拇。
這是由于浮點(diǎn)數(shù)因?yàn)橛邢薜谋忍匚粩?shù)纽乱,而不能精確地表示某些值的事實(shí)----這是數(shù)值編程的一個(gè)基本問題,而不只是在Python中出現(xiàn)敛熬,我們后面會(huì)學(xué)到小數(shù)和分?jǐn)?shù),它們是能夠避免這些限制的工具诲锹。
對(duì)于這個(gè)問題可以參考一下知乎的一個(gè)問題。為什么0.1+0.2=0.30000000000000004而1.1+2.2=3.3000000000000003庸诱?
除法:經(jīng)典除法,向下取整除法和真除法
實(shí)際上钠四,Python中有三種風(fēng)格的除法侣灶,以及兩種不同的除法運(yùn)算符,其中一種運(yùn)算符在Python3.X中有所變化。這部分內(nèi)容非常細(xì)節(jié)化栅贴,但它是Python3.X中另一個(gè)主要的變化,而且可能會(huì)破壞2.X的代碼坛缕,所以下面直接給出除法運(yùn)算符的描述。
X / Y
經(jīng)典除法和真除法宠页。在Python2.X或者之前的版本中,這個(gè)操作對(duì)于整數(shù)會(huì)省去小數(shù)部分俭嘁,對(duì)于浮點(diǎn)數(shù)會(huì)保持余項(xiàng)(小數(shù)部分)。在Python3.X變成真除法捕虽,即無論任何類型房揭。最終的浮點(diǎn)數(shù)結(jié)果都會(huì)保留小數(shù)部分。
X // Y
向下取整除法咧纠。這是從Python2.2開始新增的操作,在Python2.X和3.X中均能使用演痒,這個(gè)操作不考慮對(duì)象的類型,總是會(huì)省略結(jié)果的小數(shù)部分讯嫂,剩下最小的能夠整除的整數(shù)部分,它的結(jié)果類型取決于操作數(shù)的類型千扔。
Python中引入真除法,是為了解決經(jīng)典除法的結(jié)果依賴于操作數(shù)類型(這種結(jié)果在Python這樣的動(dòng)態(tài)語言中很難預(yù)料)的現(xiàn)象洞渤。由于這一限制,Python3.X中移除了經(jīng)典除法: / 和 // 運(yùn)算符在Python3.X中分別實(shí)現(xiàn)了真除法和向下取整除法。
在Python3.X中惋耙, / 現(xiàn)在總是執(zhí)行真除法湿酸,不管操作數(shù)的類型,都返回包含任意小數(shù)部分的一個(gè)浮點(diǎn)數(shù)結(jié)果铁坎。// 執(zhí)行向下取整除法,它截取掉余數(shù)并針對(duì)整數(shù)操作數(shù)返回一個(gè)整數(shù)襟铭,如果有一個(gè)操作數(shù)是浮點(diǎn)數(shù)類型,則返回一個(gè)浮點(diǎn)數(shù)哩都。
要注意,在Python3.X中,//的結(jié)果的數(shù)據(jù)類型總是依賴于操作數(shù)的類型:如果操作數(shù)中有一個(gè)是浮點(diǎn)數(shù)约炎,結(jié)果就是浮點(diǎn)數(shù),否則狸捕,結(jié)果就是一個(gè)整數(shù)做祝。
此外纤房,由于// 運(yùn)算符是作為依賴于整數(shù)截?cái)喑ǖ某绦蚨氲囊环N兼容性工具,因此它必須為整數(shù)返回整數(shù)舒岸。
向下取整除法 vs 截?cái)喑?/p>
一個(gè)細(xì)節(jié)是: // 運(yùn)算符有一個(gè)非正式的別名,叫做截?cái)喑ǎ贿^更準(zhǔn)確的說法應(yīng)該是向下取整除法壳澳。 // 把結(jié)果向下截?cái)嗟剿南聦樱凑嬲Y(jié)果之下的最近的整數(shù)抹镊,其直接效果是向下舍入,并不是嚴(yán)格的截?cái)喟惫剑⑶疫@對(duì)負(fù)數(shù)也有效榜贴,你可以使用Python的math模塊來查看其中的區(qū)別鹃共。
floor返回?cái)?shù)字的下舍整數(shù),所以返回的結(jié)果的是-3
和 // 結(jié)果相同霜浴,這意味著 // 不是對(duì)結(jié)果去除小數(shù)部分晶衷,而是向下獲取最近的整數(shù)。所以稱為向下取整除法阴孟。
對(duì)于trunc是對(duì)結(jié)果進(jìn)行截?cái)嗖僮髑率浣Y(jié)果總是趨近于0,嗅辣。
對(duì)于正數(shù)译暂,截?cái)喑ê拖蛳氯≌ㄊ窍嗤模瑢?duì)于負(fù)數(shù)祭衩,//向下取整除法得到的是 向下 最近的最近整數(shù)樟结。(向下驮履!向下!向下!7踉恕?趵怠)
為什么截?cái)嗪芎苤匾?/p>
Python3.X中的 / 的非截?cái)嘈袨檫€是可能會(huì)影響到大量的Python2.X程序俯萌〗锉耍可能是因?yàn)镃語言的遺留原因并扇,很多程序員仍然依賴于整數(shù)的截?cái)喑ü砣福虼怂麄儽仨殞W(xué)習(xí)在這些場(chǎng)景下使用 //励烦。今天,你應(yīng)該在編寫的所有新的Python2.X和3.X代碼中這樣做,在Python2.X中這樣做是為了向Python3.X兼容,而在Python3.X中這樣做是因?yàn)?在Python3.X中不再截?cái)唷?/p>
整數(shù)精度
除法可能在Python的各個(gè)版本中有所區(qū)別资昧,但它仍然是相對(duì)標(biāo)準(zhǔn)的屈呕。下面是一些看起來比較奇怪的內(nèi)容岳守。如目前所述,Python3.X整數(shù)支持無限制的大衅裾选:
無限制精度整數(shù)是一個(gè)方便的內(nèi)置工具外傅。例如你可以直接在Python中以美分為單位來計(jì)算美國國家財(cái)政赤字。
由于Python需要為支持?jǐn)U展精度而進(jìn)行額外的工作,因此在實(shí)際應(yīng)用中擅编,長整型數(shù)的數(shù)學(xué)運(yùn)算符通常要比支持的整數(shù)運(yùn)算更慢。然而,如果你確實(shí)要求精度本辐,更應(yīng)該慶幸Python為你提供了內(nèi)置的長整數(shù)支持天揖,而不是抱怨其性能上的不足。
復(fù)數(shù)
盡管復(fù)數(shù)比我們之前介紹的這些類型要少見一些,我上次計(jì)算這東西還是高中,但Python中的復(fù)數(shù)是一種獨(dú)特的對(duì)象類型姻政,它們通常在工程和科學(xué)應(yīng)用程序中使用公罕。如果你知道復(fù)數(shù)是什么硝清,你就會(huì)知道它的重要性校摩,如果你不知道,那么就把這一步作為選讀材料缤骨。(這是高中數(shù)學(xué)的內(nèi)容实蔽,我只記得 j**2 == -1)
復(fù)數(shù)表示為兩個(gè)浮點(diǎn)數(shù)(實(shí)部和虛部)并接在虛部增加了J或者j的后綴拨脉。我們也可以吧實(shí)部非零的復(fù)數(shù)寫作實(shí)部與虛部相加的形式解阅,并與 + 相連锈津。例如倾哺,一個(gè)復(fù)數(shù)的實(shí)部為2腊徙,虛部為-3,可以寫作 2 + -3j锁保。下面是一些復(fù)數(shù)運(yùn)算的例子做葵。
復(fù)數(shù)允許我們將它的實(shí)部和虛部作為屬性來訪問策肝,并支持所有一般的數(shù)學(xué)表達(dá)式,同時(shí)還可以通過標(biāo)準(zhǔn)的cmath模塊中的工具進(jìn)行處理坦康。因?yàn)閺?fù)數(shù)在絕大多數(shù)編程領(lǐng)域都比較罕見参淹,因此這里我們將跳過復(fù)數(shù)的其他內(nèi)容。參閱Python的語言參考手冊(cè)來獲取更多的細(xì)節(jié)当编。
十六進(jìn)制、八進(jìn)制和二進(jìn)制:字面量與轉(zhuǎn)換
Python的整數(shù)能夠以十六進(jìn)制套耕、八進(jìn)制和二進(jìn)制計(jì)數(shù)法來編寫,這作為我們迄今為止一種使用的常見的以10為底的十進(jìn)制記數(shù)法的補(bǔ)充跺株。對(duì)于十進(jìn)制生物而言欢揖,其他這三種進(jìn)制第一眼看起來充滿異域風(fēng)情瘤运,但是一些程序員會(huì)認(rèn)為他們?cè)诿枋鲆恍?shù)值時(shí)十分方便,尤其是他們能很容易地對(duì)應(yīng)到字節(jié)和位献汗。之前簡(jiǎn)述過編碼規(guī)則丧荐,這里看一些實(shí)際的例子禀综。
記住寂祥,下面這些字面量只是指定一個(gè)整數(shù)對(duì)象的值的一種替代方式荐虐。例如,在Python3.X和Python2.X中編寫的如下字面量會(huì)產(chǎn)生具有上述3中機(jī)制底數(shù)的常規(guī)整數(shù)丸凭。在內(nèi)存中缚俏,同一個(gè)整數(shù)的值是相同的,它與我們未來指定它而使用的底數(shù)無關(guān)贮乳。
這里忧换,八進(jìn)制的0o377,十六進(jìn)制的0xFF和二進(jìn)制的0b11111111向拆,都表示十進(jìn)制的255亚茬。例如,十六進(jìn)制數(shù)值中的F數(shù)字表示十進(jìn)制的15和二級(jí)的4位1111浓恳,且反映了以16為冪刹缝。因此,十六進(jìn)制數(shù)值0xFF和其他數(shù)值能像下面這樣轉(zhuǎn)換為十進(jìn)制數(shù)值
Python默認(rèn)使用十進(jìn)制顯示整數(shù)數(shù)值颈将,但它提供了內(nèi)置函數(shù)梢夯,能幫我們把整數(shù)轉(zhuǎn)換為其他進(jìn)制的字符串。
oct函數(shù)會(huì)將會(huì)十進(jìn)制轉(zhuǎn)換為八進(jìn)制數(shù)晴圾,hex函數(shù)會(huì)將十進(jìn)制數(shù)轉(zhuǎn)換為十六進(jìn)制數(shù)颂砸,而bin函數(shù)會(huì)將十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制。反過來,內(nèi)置函數(shù)int會(huì)將一個(gè)數(shù)字的字符串轉(zhuǎn)換為一個(gè)整數(shù)人乓,并能夠通過可選的第二位參數(shù)確定轉(zhuǎn)換后數(shù)字的進(jìn)制勤篮。這對(duì)于從文件中作為字符串讀取的數(shù)字來說十分有用。
eval函數(shù)色罚,將會(huì)把字符串作為Python代碼來運(yùn)行碰缔、因此,它也具有類似的效果戳护,但往往運(yùn)行的更慢金抡。它實(shí)際上會(huì)把字符串作為程序的一個(gè)片段編譯并運(yùn)行,并且它假設(shè)當(dāng)前運(yùn)行的字符串術(shù)語一個(gè)可行的來源腌且。耍小聰明的用戶也許會(huì)提交一個(gè)刪除你機(jī)器上文件的字符串竟终,因此小心使用eval調(diào)用:
最后,你也可以使用字符串格式化方法調(diào)用和表達(dá)式(它只返回?cái)?shù)字切蟋,而不是Python字面量字符串),將整數(shù)轉(zhuǎn)換為指定底的字符串:
與之類似的有%榆芦,不過現(xiàn)在不推薦使用了
按位操作
除了一般的數(shù)學(xué)運(yùn)算柄粹,Python也支持C語音中的大多數(shù)數(shù)學(xué)表達(dá)式。這些包括把那些把整數(shù)作為二級(jí)位串處理的運(yùn)算匆绣,如果你的Python代碼必須處理像網(wǎng)絡(luò)數(shù)據(jù)包驻右,串行端口或C程序產(chǎn)生的打包二級(jí)數(shù)控的這些內(nèi)容,就會(huì)十分有用崎淳。
這里不再詳細(xì)展開布爾數(shù)學(xué)的基本原理堪夭。那些必須使用它的人可能已經(jīng)找到它的如何工作的,而其他人則通常會(huì)完全地后推對(duì)這一主題的學(xué)習(xí)拣凹,但是其基礎(chǔ)知識(shí)是非常簡(jiǎn)單直接的森爽。
可以看些我寫的按位操作
第一個(gè)表達(dá)式中,二進(jìn)制數(shù)1(以1為底數(shù)嚣镜,0001)左移了兩位成為二進(jìn)制的4(0100)爬迟。上面的最后兩個(gè)運(yùn)算實(shí)現(xiàn)了一個(gè)二進(jìn)制“或”來組合為(0001|0010 = 0011),以及一個(gè)“和”來選擇共同的為(0001&0001 = 0001)菊匿。這樣的位掩碼運(yùn)算付呕,使我們可以對(duì)一個(gè)單獨(dú)的整數(shù)編碼和提取多個(gè)標(biāo)志位和值。
在該領(lǐng)域中跌捆,從Python3.0和Python2.6開始引入的二進(jìn)制和十六進(jìn)制數(shù)變得特別有用徽职,它們?cè)试S我們按照位字符串來編寫和查看數(shù)字:
這也適用于通過十六進(jìn)制字面量創(chuàng)建的數(shù)字,以及通過改變底數(shù)的數(shù)字
同樣在這一部分中佩厚,Python3.1和2.7引入了一個(gè)新的整數(shù)方法bit_length姆钉,它允許我們查詢二進(jìn)制表示一個(gè)數(shù)字時(shí)所需的位數(shù)。通過利用第四章介紹的內(nèi)置函數(shù)len,從bin字符串的長度減2育韩,也可以得到同樣的效果克蚂,(減2是減去字面量字符串開頭的“0b”)但是這種方法系效率低。
這里不會(huì)涉及到更多關(guān)于位運(yùn)算的細(xì)節(jié)筋讨。如果你需要埃叭,Python是支持的,但是按位運(yùn)算在Python這樣的高級(jí)語言中并不想在C這樣的底層語言中那么重要悉罕。
其他內(nèi)置數(shù)值工具
除了核心對(duì)象類型以外赤屋,Python提供了用于數(shù)值處理的內(nèi)置函數(shù)和內(nèi)置模塊。例如壁袄,內(nèi)置函數(shù)pow和abs用于計(jì)算冪和絕對(duì)值类早。下面是內(nèi)置模塊math中的一些例子。
我們之前介紹了截?cái)嗪拖蛳氯≌嚷撸覀円部梢杂盟纳嵛迦肷В淠康募瓤梢允乔笾担部梢允菫榱孙@示栈顷。
這里最后一個(gè)例子創(chuàng)建了通常用于打印的字符串逆日,并且它支持多重格式化選項(xiàng)。
round會(huì)四舍五入并舍棄小數(shù)位數(shù)萄凤,但人會(huì)在內(nèi)存中產(chǎn)生一個(gè)浮點(diǎn)數(shù)結(jié)果室抽,然而字符串格式化將會(huì)產(chǎn)生一個(gè)字符串,而不是數(shù)字
Python中有3種方式可以計(jì)算平方根:使用一個(gè)模塊函數(shù)靡努,一個(gè)表達(dá)式或者一個(gè)內(nèi)置函數(shù)坪圾。
要注意,內(nèi)置模塊在使用前需要先導(dǎo)入惑朦,但是想abs和round這樣的內(nèi)置函數(shù)則無須導(dǎo)入就可以直接使用兽泄。換句話說,模塊是外部的組件漾月,而內(nèi)置函數(shù)則位于一個(gè)隱含的命名空間中已日,而Python會(huì)自動(dòng)在這個(gè)命名空間中搜索程序中的名稱。
標(biāo)準(zhǔn)庫中的random模塊在使用時(shí)也必須導(dǎo)入栅屏,該模塊提供了一系列工具飘千,可以完成諸如在0和1之間挑選一個(gè)隨機(jī)浮點(diǎn)數(shù),在兩個(gè)數(shù)字之間挑選一個(gè)隨機(jī)整數(shù)的任務(wù)栈雳。
random模塊也能從一個(gè)序列中隨機(jī)選取一項(xiàng)护奈,并且隨機(jī)地打亂列表中的元素。
盡管我們需要額外的代碼使程序更加清晰明確哥纫,但random模塊很實(shí)用霉旗,對(duì)于游戲中的洗牌,在演示GUI中隨機(jī)挑選圖片,進(jìn)行統(tǒng)計(jì)模擬等都很有用處厌秒。
其他數(shù)值類型
目前读拆,我們已經(jīng)介紹了Python的核心數(shù)值類型:整數(shù),浮點(diǎn)數(shù)以及復(fù)數(shù)鸵闪。對(duì)于絕大多數(shù)程序員來說檐晕,這足以應(yīng)對(duì)大部分的使用需求。然而蚌讼,Python還自帶了一些更少見的數(shù)值類型辟灰,值得我們?cè)谶@里簡(jiǎn)要瀏覽一下,
小數(shù)類型
Python2.4中引入了一種新的核心數(shù)據(jù)類型:小數(shù)對(duì)象篡石,其正式的名稱是Decimal芥喇。從語法上來講,需要通過調(diào)用已導(dǎo)入模塊中的函數(shù)來創(chuàng)建小數(shù)凰萨,而不是通過運(yùn)行字面量表達(dá)式來創(chuàng)建继控。從功能上講,小數(shù)對(duì)象很像浮點(diǎn)數(shù)胖眷,但它們由固定的位數(shù)和小數(shù)點(diǎn)武通。因此,小數(shù)是精度固定的浮點(diǎn)數(shù)瘦材。
例如,使用小數(shù)對(duì)象仿畸,我們可以得到一個(gè)只保留兩位小數(shù)精度的浮點(diǎn)數(shù)食棕。此外,我們可以頂替如果省略和截?cái)囝~外的小數(shù)數(shù)字错沽。盡管這相對(duì)于一般的浮點(diǎn)數(shù)類型來說帶來了性能上的損失簿晓,但小數(shù)類型對(duì)表達(dá)式固定精度的特性以及對(duì)實(shí)現(xiàn)更好的數(shù)值精度而言是一個(gè)理想的工具。
小數(shù)基礎(chǔ)知識(shí)
下面是最后值得介紹的一點(diǎn)千埃,正如我們?cè)谔剿鞅容^知識(shí)時(shí)簡(jiǎn)要預(yù)習(xí)過的憔儿,浮點(diǎn)數(shù)運(yùn)算缺乏精確性,這是因?yàn)橛脕泶鎯?chǔ)數(shù)值的空間有限放可,例如谒臼,下面的計(jì)算結(jié)果應(yīng)該為零,但并非如此耀里。其結(jié)果很接近0蜈缤,但卻沒有足夠的位數(shù)來實(shí)現(xiàn)這樣的精度
在Python3.1和2.7之前的版本,打印結(jié)果會(huì)產(chǎn)生一個(gè)用戶友好的顯示格式冯挎,但并不能完全解決問題底哥,因?yàn)榕c硬件相關(guān)的的浮點(diǎn)數(shù)運(yùn)算在精確度方面有著內(nèi)在的缺陷。
不過如果使用了小數(shù)對(duì)象,那么結(jié)果將根準(zhǔn)確趾徽。
如你所見续滋,我們可以通過調(diào)用decimal模塊中的Decimal的構(gòu)造函數(shù)來創(chuàng)建一個(gè)小數(shù)對(duì)象,并傳入一個(gè)表示結(jié)果中顯示小數(shù)位數(shù)的字符串孵奶。當(dāng)你在表達(dá)式中混合不同精度的小數(shù)時(shí)疲酌,Python會(huì)自動(dòng)轉(zhuǎn)換為最高的小數(shù)位數(shù)。
你可以從一個(gè)浮點(diǎn)數(shù)對(duì)象創(chuàng)建小數(shù)對(duì)象拒课,即通過decimal徐勃。Decimal.from_float(1.25)形式的調(diào)用來實(shí)現(xiàn),而最新的Python版本允許直接使用浮點(diǎn)數(shù)來創(chuàng)建早像。這一轉(zhuǎn)換是精確的僻肖,但是有時(shí)候會(huì)產(chǎn)生默認(rèn)且龐大的小數(shù)位數(shù)。
在Python3.3以及之后的版本卢鹦,小數(shù)模塊的性能也得到了極大的提升臀脏,新版本宣稱其速度提升了10到100倍,不過這取決于基于測(cè)試的程序種類
設(shè)置全局小數(shù)精度
decimal模塊中的其他一些工具可以用來設(shè)置所有小數(shù)數(shù)值的精度冀自,安排錯(cuò)誤處理等揉稚。例如,該模塊中的一個(gè)上下文對(duì)象可以指定精度(小數(shù)位數(shù))和舍入模式(向下取整熬粗,向上取整等)搀玖,該精度將會(huì)全局性的應(yīng)用到調(diào)用線程中創(chuàng)建的所有小數(shù)。
對(duì)于處理貨幣這樣的應(yīng)用程序尤其重要驻呐,其中美分表示為兩位小數(shù)位數(shù)灌诅。在這個(gè)上下文中,小數(shù)實(shí)際上是手動(dòng)舍入和字符串格式化的一種替代方式
小數(shù)上下文管理器
你可以使用with上下文管理器嘮臨時(shí)重置小數(shù)精度含末。在with語句退出后猜拾,精度優(yōu)惠重置為初始值。
由于小數(shù)類型在實(shí)際中仍然較少用到佣盒,因此請(qǐng)參考跑一趟獲得標(biāo)準(zhǔn)庫手冊(cè)和交互式幫助來了解更多細(xì)節(jié)挎袜。
分?jǐn)?shù)類型
Python2.6和Python3.0中首次引入了一種新的數(shù)值類型Fraction(分?jǐn)?shù)),它實(shí)現(xiàn)了一個(gè)有理數(shù)對(duì)象肥惭。本質(zhì)上盯仪,它顯式地為此了一個(gè)分子和一個(gè)分母,從而避免了浮點(diǎn)數(shù)運(yùn)算的某些不精確性和局限性蜜葱。與小數(shù)一樣磨总,分?jǐn)?shù)的實(shí)現(xiàn)并不像浮點(diǎn)數(shù)靠近計(jì)算機(jī)的底層硬件。這意味著它們的性能可能不會(huì)和浮點(diǎn)數(shù)一樣優(yōu)秀笼沥,但這是也也允許它們?cè)诒匾獣r(shí)作為一種有用的標(biāo)準(zhǔn)工具蚪燕。
分?jǐn)?shù)基礎(chǔ)知識(shí)
Fraction與上一小節(jié)介紹的Decimal固定精度類型十分相似娶牌,它們都可以用來處理浮點(diǎn)數(shù)類型的數(shù)值不準(zhǔn)確性。分?jǐn)?shù)的使用和小數(shù)很像馆纳。Fraction也位于模塊中诗良,你需要導(dǎo)入其構(gòu)造函數(shù),傳入一個(gè)分子和一個(gè)分母鲁驶,從而產(chǎn)生一個(gè)分?jǐn)?shù)鉴裹。
一旦創(chuàng)建了分?jǐn)?shù),它們就可以像平常一樣用于實(shí)現(xiàn)表達(dá)式中:
分?jǐn)?shù)也可以用過浮點(diǎn)數(shù)來創(chuàng)建
分?jǐn)?shù)和小數(shù)中的數(shù)值精度
要注意钥弯,分?jǐn)?shù)和小數(shù)中的數(shù)值精度與浮點(diǎn)數(shù)運(yùn)算有所區(qū)別(浮點(diǎn)數(shù)運(yùn)算受到浮點(diǎn)數(shù)硬件底層限制的約束)径荔。出于比較目的。下面對(duì)浮點(diǎn)數(shù)對(duì)象進(jìn)行相同的操作脆霎,注意到他們的不同精度
對(duì)于那些內(nèi)存中給定的優(yōu)先位數(shù)無法精確表示的值总处,浮點(diǎn)數(shù)的局限性尤為明顯。Fraction和Decimal都提供了得到精確結(jié)果的方式睛蛛,但這需要付出一些速度和代碼冗余的代價(jià)鹦马。
此外,分?jǐn)?shù)和小數(shù)都能夠提供比浮點(diǎn)數(shù)更直觀和準(zhǔn)確的結(jié)果忆肾,它們以不同但是做到這一點(diǎn)荸频,使用有理數(shù)表示以及通過限制精度
事實(shí)上,分?jǐn)?shù)既保持了精確性客冈,又自動(dòng)簡(jiǎn)化了結(jié)果旭从,
分?jǐn)?shù)轉(zhuǎn)換和混合類型
為了支持分?jǐn)?shù)的轉(zhuǎn)換,浮點(diǎn)數(shù)現(xiàn)在有一個(gè)方法能夠產(chǎn)生它們的分子和分母比场仲,分?jǐn)?shù)有一個(gè)from_float方法和悦,并且float函數(shù)可以接受一個(gè)Fraction對(duì)象作為參數(shù)。
最終燎窘,表達(dá)式中允許摹闽,有些類型的混個(gè)蹄咖,盡管Fraction有時(shí)必須手動(dòng)的傳遞以確保精確度褐健,研究如下的交互示例來看看是如何做到的
警告,盡管你可以吧浮點(diǎn)數(shù)轉(zhuǎn)換為分?jǐn)?shù)澜汤,在某些情況下蚜迅,這么做的時(shí)候會(huì)不可避免的精度損失。因?yàn)檫@個(gè)數(shù)字在其最初的浮點(diǎn)數(shù)形勢(shì)下是不精確的俊抵。在不要時(shí)谁不,我們可以通過限制分母的最大值來簡(jiǎn)化這樣的結(jié)果
更多關(guān)于Fraction類型的細(xì)節(jié)查閱文檔。
集合
除了小數(shù)以外徽诲,Python2.4還引入了一種新的類型----集合(set)刹帕,這是一些唯一的吵血,不可變的隊(duì)形的一個(gè)無序集合體,這些對(duì)象支持與數(shù)學(xué)集合理論相對(duì)應(yīng)的操作偷溺,按照定義蹋辅,一個(gè)元素在集合中只能出現(xiàn)一次,不管它被添加了多少次挫掏,因此侦另,集合有著官方的應(yīng)用,尤其是在涉及數(shù)值和數(shù)據(jù)庫的工作中尉共。
集合是其他對(duì)象的集合體褒傅,它具有類表和字典這樣對(duì)象的么些共同行為。如袄友,集合是可迭代對(duì)象殿托,可以按照需求增長或縮短,并且可以包含多種對(duì)象類型杠河。集合的行為很像一個(gè)有鍵無值的字典碌尔,不過集合還支持更多的操作。
然而券敌,集合是無序的唾戚,而且不會(huì)把鍵映射到值,因此它們既不是序列也不映射類型待诅。它們是自成一體的類型叹坦。此外,集合本質(zhì)上具有基本的數(shù)學(xué)特性卑雁。
集合特性募书,無序,唯一测蹲,確定
集合基礎(chǔ)知識(shí)
要?jiǎng)?chuàng)建一個(gè)集合對(duì)象莹捡,你可以像內(nèi)置的set函數(shù)傳入一個(gè)序列或其他可迭代對(duì)象。
現(xiàn)在得到了集合對(duì)象扣甲,其中包含被傳入的對(duì)象內(nèi)的所有元素
集合是無序的篮赢,所以其中元素的順序是任意的,版本琉挖,計(jì)算機(jī)等種種因素都可能使其發(fā)生變化启泣。
集合通過表達(dá)式運(yùn)算符支持一般的數(shù)學(xué)集合運(yùn)算。要注意示辈,我們不能對(duì)諸如字符串寥茫,列表和元組的一般序列使用下面的預(yù)算,我們必須將字符串矾麻,列表和元組傳入set函數(shù)并創(chuàng)建了相應(yīng)的集合后纱耻,才能使用這些工具芭梯。
該規(guī)則很明顯的一個(gè)另外就是集合成員測(cè)試in.in表達(dá)式也定義為可以在全部其他集合體類型上工作,而其作用也就是成員測(cè)試弄喘。因此粥帚,我們不必將類似字符串和列表這樣的數(shù)據(jù)類型轉(zhuǎn)化為集合,就可以直接運(yùn)行in測(cè)試
除了表達(dá)式限次,集合對(duì)象還提供了與這些操作相對(duì)應(yīng)的方法芒涡,從而支持集合的修改,add方法插入一個(gè)項(xiàng)目卖漫,update在原位置求并集费尽,remove根據(jù)值輸出一個(gè)元素。
作為可迭代的容器羊始,集合也可以用于len旱幼,for循環(huán)和列表推導(dǎo)這樣的操作中,然而集合是無序的突委,所以不支持像索引和分片這樣的操作
盡管書上介紹這對(duì)于任何迭代類型都是有效的柏卤,但是我想時(shí)代是真的變了
關(guān)于創(chuàng)建集合,現(xiàn)在下面的兩種方法是相同的匀油。
集合基本上就像是沒有值的字典缘缚。字典的鍵值表在Python3.X中是視圖對(duì)象,因而它能支持像交集和并集這樣類似集合的行為敌蚜。
不管一個(gè)集合是如何被創(chuàng)建的桥滨,Python3.X都能夠只用新的字面量來顯示它、在所有的python版本中弛车,如果要?jiǎng)?chuàng)建空的集合齐媒,還是需要通過內(nèi)置函數(shù)set函數(shù)。如果你想用{}表示空集合纷跛,那么空字典該怎么辦
不可變性與凍結(jié)集合
集合是強(qiáng)大而靈活的對(duì)象喻括,但是在Python中有一個(gè)限制需要銘記,集合只能包含不可變的對(duì)象類型贫奠,因此唬血,類表和字典不能嵌入到集合中,但是如果你需要存儲(chǔ)復(fù)合對(duì)象的話叮阅,元組是可以嵌入集合的刁品。元組在集合操作中會(huì)比較其完整的值:
集合中的元組可以用來表示日期泣特,記錄浩姥,IP地址等。集合也可以包含沒虧啊状您,類型對(duì)象等勒叠。集合本身也是可變的兜挨,因此,不能后直接就嵌入到其他集合中眯分,如果需要在另一個(gè)集合中存儲(chǔ)一個(gè)集合拌汇,可以像調(diào)用set一樣調(diào)用函數(shù)frozenset,但frozenset會(huì)創(chuàng)建一個(gè)不可變的集合弊决,該集合不可修改噪舀,并且可以嵌入到其他集合中。
不是說集合不可改變飘诗,而是集合中的內(nèi)容是不可變的与倡,具有確定性,如元組昆稿,字符串纺座,數(shù)字。
集合推導(dǎo)
集合推導(dǎo)表達(dá)式類似于第四章介紹的列表推導(dǎo)的形式溉潭,但它編寫在花括號(hào)中而不是方括號(hào)中净响,并且會(huì)創(chuàng)建一個(gè)集合而不是列表。集合推導(dǎo)會(huì)運(yùn)行一個(gè)巡航并在每次迭代時(shí)手機(jī)一個(gè)表達(dá)式的結(jié)果喳瓣,通過一個(gè)循環(huán)變量來訪問當(dāng)前的迭代值以用于集合表達(dá)式中馋贤、其結(jié)果就是通過運(yùn)行代碼創(chuàng)建一個(gè)新的集合困肩,它具有所有一般的集合行為叮喳。
在該表達(dá)式中顿颅,循環(huán)部分編寫在右側(cè)飞主,而集合體表達(dá)式編寫在左側(cè)庙楚。對(duì)于列表中的每一個(gè)X分唾,給出包含X平方的一個(gè)新集合校套。對(duì)到也刻意迭代其它類型的對(duì)象纯续,例如字符串
為什么使用集合
集合操作有各種各樣的常見用途仁讨,其中一些比其數(shù)學(xué)意義更加使用羽莺,例如,去除重復(fù)項(xiàng)洞豁,利用無序進(jìn)行重新排序盐固。你只需要啊集合體轉(zhuǎn)換為一個(gè)集合然后再轉(zhuǎn)換回來即可。
集合也可以用于用于提取列表丈挟,字符串以及其他可迭代對(duì)象中的差異刁卜,當(dāng)然,集合的無序性本質(zhì)意味著結(jié)果可能和原理不匹配曙咽。
也可以通過轉(zhuǎn)換成集合蛔趴,借助集合進(jìn)行順序無關(guān)的等價(jià)性測(cè)試,這是因?yàn)轫樞蛟诩现胁恢匾欤降恼f孝情,兩個(gè)集合相當(dāng)僅當(dāng)兩個(gè)集合中的每一個(gè)元素都被另一個(gè)集合所包含鱼蝉。也就是說,撇開順序箫荡,每一個(gè)集合都是另一個(gè)集合的子集魁亦,
例如,你可能會(huì)比較程序的輸出羔挡,程序應(yīng)當(dāng)同樣的工作但是也許會(huì)產(chǎn)生不同順序的結(jié)果洁奈。在測(cè)試進(jìn)行前進(jìn)行排序可以獲得等價(jià)性測(cè)試的效果,但是幾個(gè)不需要開銷高昂的排序绞灼,而排序允許其結(jié)果支持集合所不支持的相對(duì)大小比較睬魂。
當(dāng)你遍歷一個(gè)圖或者其他有環(huán)結(jié)構(gòu)時(shí),集合可以用于記錄已訪問的位置镀赌。最后氯哮,當(dāng)你在處理較大的數(shù)據(jù)時(shí),兩個(gè)集合的交集包含了兩個(gè)種類中共有的對(duì)象商佛,并集包含了兩個(gè)集合中的所有元素喉钢。
你可以在Python庫手冊(cè)以及關(guān)系數(shù)據(jù)庫理論的一些相關(guān)資料中,找到關(guān)于集合操作的更多細(xì)節(jié)良姆。
布爾型
有些人可能認(rèn)為Python的布爾類型本質(zhì)上是數(shù)值肠虽,因?yàn)樗瑑蓚€(gè)值True和False,而且就算整數(shù)1和0的定制版玛追,只不過打印時(shí)有所不同税课。盡管這是大多數(shù)程序員所需了解的全部,我們還是要稍稍深入的探索布爾類型
更正式的說痊剖,今天的Python有一個(gè)名為boll的顯示布爾數(shù)據(jù)類型韩玩,帶有True和False作為可用且預(yù)賦值的內(nèi)置名稱。在內(nèi)部陆馁,名稱True和False是bool的示例找颓,而bool實(shí)際上只是內(nèi)置整數(shù)類型int的之類(從面向?qū)ο蟮慕嵌葋砜矗rue和False的行為與在說話1和0是一樣的叮贩,只不過他們有獨(dú)特的顯示邏輯:他們是作為關(guān)鍵字True和False顯示的击狮,而不是整數(shù)1和0.bool為這兩個(gè)對(duì)象重新定義了str和repr的字符串格式
由于該定制,布爾類型表達(dá)式在交互式命令行模式的輸出就成為關(guān)鍵字True和False來顯示益老,而不是曾經(jīng)的1和0彪蓬。此外,布爾類型讓真值在你的代碼中更加明顯捺萌。例如档冬,一個(gè)無限循環(huán)現(xiàn)在可以寫為while True:而不是更不直觀的while 1:。類似的,通過使用flag = False可以更清楚的設(shè)置標(biāo)志位捣郊。
同樣,對(duì)于大多數(shù)實(shí)際場(chǎng)景慈参,你可以把True和False看做預(yù)定義的設(shè)置為整數(shù)1和0的名稱呛牲。不過很多程序員都曾把True和False預(yù)先賦值為1和0,所以新的bool類型直接讓其成為一種標(biāo)準(zhǔn)驮配。但它的實(shí)現(xiàn)會(huì)導(dǎo)致奇怪的結(jié)果娘扩。因?yàn)門rue僅僅是定制了顯示格式的整數(shù)1、所以在Python中Trued++4得到了整數(shù)5
因?yàn)槟憧赡懿粫?huì)在真正的Python代碼中遇到像上面例子中最后一個(gè)那樣的表達(dá)式壮锻,所以你完全可以忽略其任何更深?yuàn)W的形而上的含義琐旁。
數(shù)值擴(kuò)展
盡管跑一趟后的核心數(shù)值類型提供的功能對(duì)于大多數(shù)應(yīng)用程序而言已經(jīng)足夠用了,但還有大量的第三方開源擴(kuò)展可以用來解決更加專門的需求猜绣。
例如灰殴,如果你需要做一些正式的數(shù)字計(jì)算,一個(gè)叫做NumPy的可選Python擴(kuò)展提供了高級(jí)的數(shù)值編程工具掰邢,例如矩陣數(shù)據(jù)類型牺陶,向量處理和精密的計(jì)算庫。
本章小結(jié)
本章介紹了Python數(shù)值對(duì)象及其運(yùn)算辣之。在這個(gè)過程中掰伸,我們學(xué)習(xí)了表核準(zhǔn)的整數(shù)和浮點(diǎn)數(shù)類型,以及一些更加奇特和少見的類型怀估,例如復(fù)數(shù)狮鸭,小數(shù),分?jǐn)?shù)和集合多搀。我們也學(xué)習(xí)了Python的表達(dá)式語法歧蕉、類型轉(zhuǎn)換、按位運(yùn)算以及各種在程序中編寫數(shù)字的字面量形式康铭。
接下來在本書的這一部分中廊谓,我們將繼續(xù)更深入的類型流程,并繼續(xù)學(xué)習(xí)下一個(gè)對(duì)象類型----字符串的一些細(xì)節(jié)麻削,然而在下一章中蒸痹,我們將花一些時(shí)間來探索這里用到的變量賦值機(jī)制以及更多細(xì)節(jié)。這也行是Python中最基本的概念呛哟,所以在繼續(xù)學(xué)習(xí)之前叠荠,你需要好好閱讀下一章,不過首先扫责,讓我們照例做一下章節(jié)測(cè)試榛鼎。
回顧一下本章內(nèi)容,首先是數(shù)值類型種類,它們的字面量者娱,然后是表達(dá)式運(yùn)算符抡笼,運(yùn)算的優(yōu)先級(jí)。了解一下變量黄鳍,數(shù)值的顯示格式推姻,str和repr,鏈?zhǔn)奖容^框沟。關(guān)于Python3.X的除法藏古,/是真除法,//是向下取整除法忍燥。復(fù)數(shù)簡(jiǎn)單了解一下格式拧晕。進(jìn)制轉(zhuǎn)換,本質(zhì)梅垄,一些按位操作厂捞。
小數(shù)與分?jǐn)?shù),其意義以及表示方法队丝。集合相關(guān)知識(shí)蔫敲。3種特性,無序炭玫,唯一奈嘿,確定,及其應(yīng)用吞加。布爾類型裙犹。知道一個(gè)NB的庫NumPy。
下面背誦并默寫本章習(xí)題
本章習(xí)題
1.Python中的表達(dá)式2 * (3 + 4)的值是多少衔憨?
結(jié)果是14叶圃,即2*7的結(jié)果,因?yàn)槔ㄌ?hào)強(qiáng)制讓加法在乘法之前運(yùn)算践图。
2.Python中表達(dá)式2 * 3 + 4 的值是多少掺冠?
結(jié)果是10,即6+4的結(jié)果码党。Python的運(yùn)算符優(yōu)先級(jí)法則適用于沒有括號(hào)存在的場(chǎng)合德崭,按照表5-1,除法的優(yōu)先級(jí)要比加法的優(yōu)先級(jí)高(先進(jìn)行乘法運(yùn)算)揖盘。
3.Python中表達(dá)式2 + 3* 4 的值是多少眉厨?
結(jié)果是14,即2+12的結(jié)果兽狭,與上一題一樣是優(yōu)先級(jí)的原因憾股。
4鹿蜀。你可以使用壽命工具來計(jì)算一個(gè)數(shù)字的平方根以及它的平方?
當(dāng)你導(dǎo)入math模塊后服球,即可求平方根茴恰、pi以及正切等函數(shù)。為了獲得一個(gè)數(shù)字的平方根斩熊,import math后調(diào)用math往枣。sqrt(N)。為了得到一個(gè)數(shù)字的平方座享,使用指數(shù)表達(dá)式X ** 2婉商,或者內(nèi)置函數(shù)pow(X,2).上述兩種方式都可以用來計(jì)算一個(gè)數(shù)的0.5次方(例如X ** .5)
5.表達(dá)式1 + 2. 0 +3 的結(jié)果是什么類型似忧?
結(jié)果是一個(gè)浮點(diǎn)數(shù)渣叛,整型將轉(zhuǎn)換升級(jí)成浮點(diǎn)數(shù),也就是該表達(dá)式中最復(fù)雜的類型盯捌,然后采用浮點(diǎn)數(shù)的運(yùn)算法則進(jìn)行計(jì)算淳衙。
6.如何截?cái)嗷蛏崛ジ↑c(diǎn)數(shù)的小數(shù)部分?
int(N)函數(shù)和math饺著。trunc(N)函數(shù)可以省略小數(shù)部分箫攀,而round(N,digit)函數(shù)會(huì)四舍五入。我們可以使用math.floor(N)來計(jì)算向下取整幼衰,并且使用字符串格式化操作來舍入以便于顯示靴跛。
7.如果講一個(gè)整數(shù)轉(zhuǎn)換為浮點(diǎn)數(shù)?
float(N)將整數(shù)轉(zhuǎn)換為浮點(diǎn)數(shù)渡嚣,在表達(dá)式中混合整數(shù)和浮點(diǎn)數(shù)也會(huì)實(shí)現(xiàn)轉(zhuǎn)換梢睛。在某種意義上,Python3.X的 / 除法也會(huì)轉(zhuǎn)換识椰,它總是返回一個(gè)包含小數(shù)部分的浮點(diǎn)數(shù)結(jié)果绝葡,即便兩個(gè)操作數(shù)都是整數(shù)。
8.任何將一個(gè)整數(shù)顯示成八進(jìn)制腹鹉、十六進(jìn)制或二進(jìn)制的形式藏畅?
內(nèi)置函數(shù)oct(I)和hex(I)會(huì)將整數(shù)以八進(jìn)制和十六進(jìn)制數(shù)字符串的形式返回。在Python2.6.3.0以及之后的版本中功咒,bin(I)也會(huì)返回一個(gè)數(shù)字的二進(jìn)制數(shù)字字符串愉阎,%字符串格式化表達(dá)式和字符串format方法也可以進(jìn)行這樣的轉(zhuǎn)換。
9.任何將一個(gè)八進(jìn)制力奋、十六進(jìn)制或二進(jìn)制的字符串轉(zhuǎn)換成一般的整數(shù)诫硕?
int(S,base)函數(shù)可以用來將一個(gè)八進(jìn)制和十六進(jìn)制的字符串轉(zhuǎn)換為支持的整數(shù)(傳入8、16或2作為base參數(shù))刊侯。eval(S)函數(shù)也能夠用作這個(gè)目的章办,但是運(yùn)行起來開銷更大且可能導(dǎo)致安全問題。注意整數(shù)總是在計(jì)算機(jī)內(nèi)存中以二進(jìn)制形式存儲(chǔ);這些只不過是顯示字符串格式的轉(zhuǎn)換而已藕届。