溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python 數(shù)值類型——《Python學(xué)習(xí)手冊(cè)》第 5 章學(xué)習(xí)筆記

發(fā)布時(shí)間:2020-07-30 01:04:08 來(lái)源:網(wǎng)絡(luò) 閱讀:299 作者:賓果go 欄目:編程語(yǔ)言

數(shù)值類型基礎(chǔ)知識(shí)

在 Python 中,數(shù)字并不真的是只是一種對(duì)象類型,而是一組相似類型的分類。完整的 Python 數(shù)值類型工具包括:整數(shù)和浮點(diǎn)對(duì)象;復(fù)數(shù)對(duì)象小數(shù):固定精度對(duì)象分?jǐn)?shù):有理數(shù)對(duì)象集合:帶有數(shù)值運(yùn)算的集合體布爾值:真和假內(nèi)置函數(shù)模塊:round、math、random 等;表達(dá)式:無(wú)限制整數(shù)精度;位運(yùn)算;十六進(jìn)制、八進(jìn)制和二進(jìn)制格式第三方擴(kuò)展:向量、庫(kù)、可視化、作圖等。

數(shù)值字面量

Python 提供了整數(shù)(包括正整數(shù)、負(fù)整數(shù)和零)以及浮點(diǎn)數(shù)(帶有小數(shù)部分的數(shù)字)作為其基本類型。

整數(shù)和浮點(diǎn)數(shù)字面量

整數(shù)寫成十進(jìn)制數(shù)字的串。浮點(diǎn)數(shù)帶一個(gè)小數(shù)點(diǎn),也可以加上一個(gè)科學(xué)技術(shù)標(biāo)志 e 或者 E。浮點(diǎn)數(shù)在標(biāo)準(zhǔn) CPython 中采用 C 語(yǔ)言中的“雙精度”來(lái)實(shí)現(xiàn),因此,其精度與用來(lái)構(gòu)建 Python 解釋器的 C 編譯器所給定的精度一樣。

Python 2.X 中的整數(shù):一般整數(shù)和長(zhǎng)整數(shù)

Python 2.X 中有兩種整數(shù)類型:一般整數(shù)(通常 32 位)和長(zhǎng)整數(shù)(無(wú)限精度),并且一個(gè)整數(shù)可以以 l 或 L 結(jié)尾,從而強(qiáng)制它轉(zhuǎn)換為長(zhǎng)整數(shù)。

Python 3.X 中的整數(shù):?jiǎn)为?dú)的一種類型

Python 3.X 中,一般整數(shù)和長(zhǎng)整數(shù)類型合二為一——只有整數(shù)這一種,它自動(dòng)地支持 Python 2.X 中的長(zhǎng)整數(shù)類型所擁有的無(wú)窮精度。因此,整數(shù)在程序中不再有末尾的 l 或 L 表示,并且整數(shù)也不再顯示這個(gè)字符。

十六進(jìn)制、八進(jìn)制和二進(jìn)制字面量

整數(shù)可以編寫為十進(jìn)制(以 10 為基數(shù))、十六進(jìn)制(以 16 為基數(shù))、八進(jìn)制(以 8 為基數(shù))和二進(jìn)制(以 2 為基數(shù))形式。十六進(jìn)制數(shù)以 0x 為 0X 開頭,后面接十六進(jìn)制的數(shù)字 0-9 和 A-F。十六進(jìn)制的數(shù)字編寫成大寫或小寫都可以。八進(jìn)制數(shù)字面量以數(shù)字 0o 或 0O 開頭(數(shù)字 0 后面加小寫或大寫的字母“o”),后面跟數(shù)字 0-7 構(gòu)成的數(shù)字串。Python 3.X 中的二進(jìn)制字面量以 0b 或 0B 開頭,后面跟著二進(jìn)制數(shù)字(0-1)。
要注意,所有這些字面量在程序代碼中都產(chǎn)生一個(gè)整數(shù)對(duì)象,它們僅僅是特定值的不同語(yǔ)法表示。內(nèi)置函數(shù) hex(I)、oct(I) 和 bin(I) 把一個(gè)整數(shù)轉(zhuǎn)換為這 3 種進(jìn)制表示的字符串,并且 int(str,base) 根據(jù)每個(gè)給定的進(jìn)制把一個(gè)運(yùn)行時(shí)字符串轉(zhuǎn)換為一個(gè)整數(shù)。

復(fù)數(shù)

Python 的復(fù)數(shù)字面量寫成實(shí)部 + 虛部的寫法,這里虛部是以 j 或 J 結(jié)尾。其中,虛部可以獨(dú)立于實(shí)部單獨(dú)存在。復(fù)數(shù)也可以通過(guò)內(nèi)置函數(shù) complex(real,imag) 來(lái)創(chuàng)建。

Python 表達(dá)式運(yùn)算符

表達(dá)式的定義是:數(shù)字(或其他對(duì)象)與運(yùn)算符相結(jié)合,并被 Python 在執(zhí)行時(shí)計(jì)算為一個(gè)值。
下表為 Python 表達(dá)式運(yùn)算符及程序,在該表中,運(yùn)算符從上到下優(yōu)先級(jí)逐漸增高,也就是說(shuō)越下面的表達(dá)式“綁定得越緊”。

運(yùn)算符 描述
yield x 生成器函數(shù) send 協(xié)議
lambda args: expression 創(chuàng)建匿名函數(shù)
x if y else z 三元選擇表達(dá)式(僅當(dāng) y 為真時(shí),x 才會(huì)被計(jì)算)
x or y 邏輯或(僅當(dāng) x 為假時(shí),y 才會(huì)被計(jì)算)
x and y 邏輯與(僅當(dāng) x 為真時(shí),y 才會(huì)被計(jì)算)
not x 邏輯非
x in y, x not in y 成員關(guān)系(可迭代對(duì)象、集合)
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)
  • 在 Python 2.X 中,值的不相等可以寫成 X != Y 或 X <> Y。在 Python 3.X 中,X <> Y 的形式被移除了。
  • 在 Python 2.X 中,一個(gè)反引號(hào)表達(dá)式 `X` 與 repr(X) 的作用相同,目的是轉(zhuǎn)換對(duì)象以顯示字符串。由于它不易理解,因此 Python 3.X 移除了這個(gè)表達(dá)式。
  • 在 Python 2.X 和 Python 3.X 中,X // Y 對(duì)應(yīng)的向下取整除法表達(dá)式總是會(huì)把商的小數(shù)部分去掉。在 Python 3.X 中,X / Y 表達(dá)式會(huì)執(zhí)行真除法(保留了商的小數(shù)部分),在 Python 2.X 中,X / Y 表達(dá)式會(huì)執(zhí)行經(jīng)典除法(截?cái)酁檎麛?shù))。
  • [...] 語(yǔ)法同時(shí)用于列表字面量、列表推導(dǎo)表達(dá)式。列表推導(dǎo)表達(dá)式會(huì)執(zhí)行隱式的循環(huán),并把表達(dá)式的結(jié)果收集到一個(gè)新列表中。
  • (...) 語(yǔ)法用于元組和表達(dá)式分組,以及生成器表達(dá)式。生成器是一種能夠按需產(chǎn)生結(jié)果的列表推導(dǎo),而不是一次性創(chuàng)建完整的結(jié)果列表。
  • {...} 語(yǔ)法用于字典字面量,并且在 Python 3.X 和 2.7 中可以表示集合字面量以及字典和集合推導(dǎo)。
  • yield 和 三元 if/else 表達(dá)式在 Python 2.5 之后的版本可用。如果 yield 不是單獨(dú)地位于一條賦值語(yǔ)句的右邊,需要使用圓括號(hào)。
  • 在 Python 2.X 中,比較混合類型的相對(duì)大小是允許的,這會(huì)把數(shù)字轉(zhuǎn)換為一個(gè)普通類型,并且根據(jù)類型名稱來(lái)排序其他的混合類型;而在 Python 3.X 中,比較非數(shù)字的混合類型的相對(duì)大小是不允許的,并且會(huì)引發(fā)異常;而通過(guò)代理的排序也會(huì)引發(fā)異常。
  • 在 Python 3.X 中,字典的相對(duì)大小比較也不再支持(支持等價(jià)性測(cè)試);比較 sorted(aDict.items()) 是一種可能的替代。

混合類型向上轉(zhuǎn)換

在混合類型的表達(dá)式中,Python 首先將被操作的對(duì)象轉(zhuǎn)換成其中最復(fù)雜的操作數(shù)的類型,然后再對(duì)相同類型的操作數(shù)進(jìn)行數(shù)學(xué)運(yùn)算。在 Python 中,整數(shù)比浮點(diǎn)數(shù)簡(jiǎn)單,浮點(diǎn)數(shù)比復(fù)數(shù)簡(jiǎn)單。所有這些混合類型轉(zhuǎn)換僅適用于數(shù)值類型(例如一個(gè)整數(shù)和一個(gè)浮點(diǎn)數(shù))的混合,這包括那些使用數(shù)字和比較運(yùn)算符的表達(dá)式。

數(shù)字的實(shí)際應(yīng)用

變量與基礎(chǔ)表達(dá)式

在 Python 中:

  • 變量在第一次賦值時(shí)被創(chuàng)建。
  • 變量在表達(dá)式中使用時(shí),會(huì)被替換成它們的值。
  • 變量在表達(dá)式中使用之前,必須已被賦值。
  • 變量引用對(duì)象,而且從不需要事先聲明。

在 Python 中不需要提前聲明變量,但變量在使用之前必須至少被賦值一次。實(shí)際上,這意味著在進(jìn)行累加計(jì)數(shù)器之前必須先將它們賦值為 0;在列表尾部添加元素之前必須先初始化一個(gè)空列表。

數(shù)值的顯示格式

str 和 repr 顯示格式

str 和 repr 都會(huì)把任意對(duì)象轉(zhuǎn)換成對(duì)應(yīng)的字符串表示:repr 會(huì)產(chǎn)生看起來(lái)像代碼的結(jié)果。str 轉(zhuǎn)換為一種通常對(duì)用戶更加友好的格式。

>>> repr('spam')
"'spam'"
>>> str('spam')
'spam'

普通比較與鏈?zhǔn)奖容^

Python 允許將相對(duì)大小比較測(cè)試鏈接起來(lái),形成如范圍測(cè)試的連續(xù)比較。例如,表達(dá)式(A < B < C)測(cè)試了 B 是否位于 A 和 C 直接,等同于布爾測(cè)試( A < B and B < C )。

>>> A = 2
>>> B = 4
>>> C = 6
>>> A < B < C
True
>>> A < B and B < C
True
>>> A < B > C
False
>>> A < B and B > C
False
>>> 1 == 2 < 3
False
>>> 1.1 + 2.2 == 3.3
False
>>> 1.1 + 2.2
3.3000000000000003
>>> int(1.1 + 2.2)
3
>>> int(3.3)
3
>>> int(1.1 + 2.2) == int(3.3)
True

除了鏈接,數(shù)值比較是基于相對(duì)大小的??赡芨↑c(diǎn)數(shù)不會(huì)總是按照預(yù)期的想法工作,這是由于浮點(diǎn)數(shù)因?yàn)橛邢薜谋忍匚粩?shù),而不能精確地表示某些值。這是數(shù)值編程的一個(gè)基本問(wèn)題,而不只是在 Python 中出現(xiàn)。

除法:經(jīng)典除法、向下取整除法和真除法

除法的行為在 Python 3.X 和 Python 2.X 中略有差異。

X / Y
經(jīng)典除法和真除法。在 Python 2.X 或之前的版本中,這個(gè)操作對(duì)于整數(shù)會(huì)省去小數(shù)部分,對(duì)于浮點(diǎn)數(shù)會(huì)保持余項(xiàng)(小數(shù)部分)。在 Python 3.X 中將會(huì)變成真除法,即無(wú)論任何類型,最終的浮點(diǎn)數(shù)結(jié)果都會(huì)保留小數(shù)部分。

X // Y
向下取整除法。這是從 Python 2.2 開始新增的操作,在 Python 2.X 和 Python 3.X 中均能使用。這個(gè)操作不考慮操作對(duì)象的類型,總是會(huì)省略結(jié)果的小數(shù)部分,剩下的最小的能整除的整數(shù)部分。它的結(jié)果取決于操作數(shù)的類型。

概括地說(shuō),
在 Python 3.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ù)。
在 Python 2.X 中,/ 表示經(jīng)典除法,如果兩個(gè)操作數(shù)都是整數(shù)的話,執(zhí)行截?cái)嗟恼麛?shù)除法;否則,執(zhí)行浮點(diǎn)除法。// 執(zhí)行向下取整除法,并且像在 Python 3.X 中那樣工作,對(duì)于整數(shù)執(zhí)行截?cái)喑?,?duì)于浮點(diǎn)數(shù)執(zhí)行浮點(diǎn)除法。

[root@binguo ~]# python
Python 3.6.1 (default, Sep 19 2019, 17:19:47) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 10 / 4
2.5
>>> 10 / 4.0
2.5
>>> 10 // 4
2
>>> 10 // 4.0
2.0
>>> 10 / 4,10 / -4
(2.5, -2.5)
>>> 10 // 4,10 // -4
(2, -3)

十六進(jìn)制、八進(jìn)制和二進(jìn)制:字面量與轉(zhuǎn)換

要記得的是,下面的這些字面量只是指定一個(gè)整數(shù)對(duì)象的值的一種替代方式。在 Python 3.X 和 Python 2.X 中編寫的如下字面量會(huì)產(chǎn)生具有上述 3 種進(jìn)制數(shù)的常規(guī)整數(shù)。在內(nèi)存中,同一個(gè)整數(shù)的值是相同的,它與我們?yōu)榱酥付ㄋ褂玫牡讛?shù)無(wú)關(guān)

>>> 0o1,0o20,0o377
(1, 16, 255)
>>> 0x01,0x10,0xFF
(1, 16, 255)
>>> 0b1,0b10000,0b11111111
(1, 16, 255)

Python 默認(rèn)用十進(jìn)制值(以 10 為底)顯示整數(shù)數(shù)值,也提供了能把整數(shù)轉(zhuǎn)換為其他進(jìn)制的數(shù)字字符串(以 Python 字面量的形式)。

>>> oct(64),hex(64),bin(64)
('0o100', '0x40', '0b1000000')

oct 函數(shù)將十進(jìn)制數(shù)轉(zhuǎn)為八進(jìn)制數(shù),hex 函數(shù)會(huì)將十進(jìn)制轉(zhuǎn)換為十六進(jìn)制數(shù),bin 函數(shù)會(huì)將十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制。
反過(guò)來(lái),內(nèi)置函數(shù) int 會(huì)將一個(gè)數(shù)字的字符串轉(zhuǎn)換為一個(gè)整數(shù),并通過(guò)可選的第二位參數(shù)來(lái)確定轉(zhuǎn)換后數(shù)字的進(jìn)制。

>>> 64,0o100,0x40,0b1000000
(64, 64, 64, 64)
>>> int('64'),int('100',8),int('40',16),int('1000000',2)
(64, 64, 64, 64)

eval 函數(shù),會(huì)把字符串作為 Python 代碼來(lái)運(yùn)行。因此,它也具有和 int 函數(shù)類似的功能,但運(yùn)行的更慢。實(shí)際上 eval 函數(shù)會(huì)把字符串作為程序的一個(gè)片段編譯運(yùn)行,并且假設(shè)當(dāng)前運(yùn)行的字符串屬于一個(gè)可信的來(lái)源。因此要小心使用 eval 調(diào)用。

>>> eval('64'),eval('0o100'),eval('0x40'),eval('0b1000000')
(64, 64, 64, 64)

最后,也可以使用字符串格式化方法調(diào)用和表達(dá)式(它只返回?cái)?shù)字,而不是 Python 的字面量字符串),將整數(shù)轉(zhuǎn)換為指定底的字符串:

>>> '{0:o},{1:x},{2:b}'.format(64,64,64)
'100,40,1000000'
>>> '%o,%x,%x,%X' % (64,64,255,255)
'100,40,ff,FF'

按位操作

下面是實(shí)際中 Python 的按位表達(dá)式運(yùn)算符中的一部分,能夠?qū)崿F(xiàn)整數(shù)的按位移動(dòng)及布爾運(yùn)算:

>>> x = 1
>>> x << 2
4
>>> x | 2
3
>>> x & 1
1

在第一個(gè)表達(dá)式中,二進(jìn)制數(shù) 1(以 2 為底數(shù),0001)左移了兩位,成為二進(jìn)制的 4(0100)。
第二個(gè)表達(dá)式實(shí)現(xiàn)了一個(gè)二進(jìn)制“或”來(lái)組合位(0001|0010=0011)。
第三個(gè)表達(dá)式實(shí)現(xiàn)了一個(gè)二進(jìn)制“和”來(lái)選擇共同的位(0001&0001=0001)。

在 Python 3.0 中,可以按照位字符串來(lái)編寫和查看數(shù)字。

>>> x = 0b0001
>>> x
1
>>> x << 2
4
>>> bin(x << 2)
'0b100'
>>> bin(x | 0b010)
'0b11'
>>> bin(x & 0b1)
'0b1'
>>> x = 0xFF
>>> x
255
>>> bin(x)
'0b11111111'
>>> bin(x ^ 0b10101010)
'0b1010101'
>>> int('01010101',2)
85
>>> hex(85)
'0x55'

Python 3.1 和 2.7 引入了一個(gè)新的整數(shù)方法 bit_length,它可以查詢以二進(jìn)制表示一個(gè)數(shù)字的值時(shí)所需的位數(shù)。也可以通過(guò)內(nèi)置函數(shù) len,從 bin 字符串的長(zhǎng)度減 2(代表字面量字符串開頭的“0b”),也可以得到同樣的結(jié)果。

>>> x = 99
>>> bin(x),x.bit_length(),len(bin(x))-2
('0b1100011', 7, 7)
>>> bin(256),(256).bit_length(),len(bin(256))-2
('0b100000000', 9, 9)

其他數(shù)值類型

Python 的核心數(shù)值類型:整數(shù)、浮點(diǎn)數(shù)和復(fù)數(shù)。這里介紹一些 Python 自帶的更少見(jiàn)的數(shù)值類型。

小數(shù)類型

Python 2.4 中引入一種新的核心數(shù)據(jù)類型:小數(shù)對(duì)象。其正式名稱是 Decimal。從語(yǔ)法上來(lái)講,需要通過(guò)調(diào)用已導(dǎo)入模塊中的函數(shù)來(lái)創(chuàng)建小數(shù),而不是通過(guò)運(yùn)行字面量表達(dá)式來(lái)創(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ù)字。

小數(shù)基礎(chǔ)知識(shí)

首先,浮點(diǎn)數(shù)運(yùn)算缺乏精確性,這是因?yàn)橛脕?lái)存儲(chǔ)數(shù)值的空間有限??梢允褂眯?shù)對(duì)象是的一些浮點(diǎn)數(shù)運(yùn)算結(jié)果更加精確:

>>> 0.1 + 0.1 + 0.1 - 0.3
5.551115123125783e-17
>>> from decimal import Decimal
>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Decimal('0.0')

當(dāng)在表達(dá)式中混合使用精度不同的小數(shù)時(shí),Python 會(huì)自動(dòng)轉(zhuǎn)換為最高的小數(shù)位數(shù)。

>>> Decimal('0.1') + Decimal('0.10') + Decimal('0.1') - Decimal('0.3')
Decimal('0.00')

在 Python 2.7、3.1 及之后的版本中,也可以通過(guò) decimal.Decimal.from_float(1.25) 的形式從一個(gè)浮點(diǎn)數(shù)對(duì)象創(chuàng)建小數(shù)對(duì)象,最新的版本允許直接創(chuàng)建。這一轉(zhuǎn)換是精確的,但有時(shí)會(huì)產(chǎn)生默認(rèn)且龐大的小數(shù)位數(shù)。

>>> Decimal(0.1) + Decimal(0.1) + Decimal(0.1) - Decimal(0.3)
Decimal('2.775557561565156540423631668E-17')
設(shè)置全局小數(shù)精度

decimal 模塊中的其他一些工具可以用來(lái)設(shè)置所有小數(shù)數(shù)值的精度,安排錯(cuò)誤處理等。

>>> import decimal
>>> decimal.Decimal(1)/decimal.Decimal(7)
Decimal('0.1428571428571428571428571429')
>>> decimal.getcontext().prec = 4
>>> decimal.Decimal(1)/decimal.Decimal(7)
Decimal('0.1429')
>>> decimal.Decimal(0.1) + decimal.Decimal(0.1) + decimal.Decimal(0.1) - decimal.Decimal(0.3)
Decimal('1.110E-17')
小數(shù)上下文管理器

在 Python 2.6 和 3.0 及之后的版本中,可以使用 with 上下文管理器語(yǔ)句來(lái)臨時(shí)重置小數(shù)精度。

>>> import decimal
>>> decimal.Decimal('1.00')/decimal.Decimal('3.00')
Decimal('0.3333333333333333333333333333')
>>> with decimal.localcontext() as ctx:
...     ctx.prec = 2
...     decimal.Decimal('1.00')/decimal.Decimal('3.00')
... 
Decimal('0.33')
>>> decimal.Decimal('1.00')/decimal.Decimal('3.00')
Decimal('0.3333333333333333333333333333')

分?jǐn)?shù)類型

Python 2.6 和 3.0 首次引入了新的數(shù)值類型 Fraction(分?jǐn)?shù)),它實(shí)現(xiàn)了一個(gè)有理數(shù)對(duì)象。本質(zhì)上,它顯式地保持了一個(gè)分子和一個(gè)分母,從而避免了浮點(diǎn)數(shù)運(yùn)算的某些不精確性和局限性。

分?jǐn)?shù)基礎(chǔ)知識(shí)

分?jǐn)?shù)的使用方式和小數(shù)很像。

>>> from fractions import Fraction
>>> x = Fraction(1,3)
>>> y = Fraction(4,6)
>>> x
Fraction(1, 3)
>>> y
Fraction(2, 3)
>>> print(x,y)
1/3 2/3
>>> x + y
Fraction(1, 1)
>>> x - y
Fraction(-1, 3)
>>> x * y
Fraction(2, 9)
>>> Fraction('.25')
Fraction(1, 4)
>>> Fraction('1.25')
Fraction(5, 4)
>>> Fraction(1.25)
Fraction(5, 4)
分?jǐn)?shù)和小數(shù)中的數(shù)值精度

對(duì)浮點(diǎn)數(shù)對(duì)象進(jìn)行相同的運(yùn)算,在內(nèi)存中它們?nèi)匀皇遣粶?zhǔn)確的。

>>> a = 1/3.0
>>> b = 4/6.0
>>> a
0.3333333333333333
>>> b
0.6666666666666666
>>> a + b
1.0
>>> a - b
-0.3333333333333333
>>> a * b
0.2222222222222222

在下面的例子中,浮點(diǎn)數(shù)并不能準(zhǔn)確地給出期望的答案 0,但分?jǐn)?shù)和小數(shù)做到了。

>>> 0.1 + 0.1 + 0.1 - 0.3
5.551115123125783e-17
>>> from fractions import Fraction
>>> Fraction(1,10) + Fraction(1,10) + Fraction(1,10) - Fraction(3,10)
Fraction(0, 1)
>>> from decimal import Decimal
>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') - Decimal('0.3')
Decimal('0.0')

分?jǐn)?shù)和小數(shù)都能提供比浮點(diǎn)數(shù)更直觀和準(zhǔn)確的結(jié)果,它們分別通過(guò)使用有理數(shù)表示以及通過(guò)限制精度做到這點(diǎn)。

>>> 1 / 3
0.3333333333333333
>>> Fraction(1,3)
Fraction(1, 3)
>>> import decimal
>>> decimal.getcontext().prec = 2
>>> Decimal(1)/Decimal(3)
Decimal('0.33')

實(shí)際上,分?jǐn)?shù)既保持了精確性,又自動(dòng)簡(jiǎn)化了結(jié)果。

>>> (1 / 3) + (6 / 12)
0.8333333333333333
>>> Fraction(6,12)
Fraction(1, 2)
>>> Fraction(6,12) + Fraction(1,3)
Fraction(5, 6)
>>> decimal.Decimal(str(1/3)) + decimal.Decimal(str(6/12))
Decimal('0.83')
分?jǐn)?shù)轉(zhuǎn)換和混用類型

為了支持分?jǐn)?shù)的轉(zhuǎn)換,浮點(diǎn)數(shù)對(duì)象現(xiàn)在有一個(gè)方法,能夠產(chǎn)生它們的分子和分母比,分?jǐn)?shù)有一個(gè) from_float 方法,并且 float 函數(shù)可以接受一個(gè) Fraction 對(duì)象作為參數(shù)。

>>> (2.5).as_integer_ratio()
(5, 2)
>>> f = 2.5
>>> z = Fraction(\*f.as_integer_ratio())
>>> z
Fraction(5, 2)
>>> x = Fraction(1,3)
>>> x
Fraction(1, 3)
>>> x +z
Fraction(17, 6)
>>> float(x)
0.3333333333333333
>>> float(z)
2.5
>>> float(x+z)
2.8333333333333335
>>> 17/6
2.8333333333333335
>>> Fraction.from_float(1.75)
Fraction(7, 4)
>>> Fraction(\*(1.75).as_integer_ratio())
Fraction(7, 4)

集合

Python 2.4 引入了集合(set),這是唯一的、不可變的對(duì)象的一個(gè)無(wú)序集合體(collection),這些對(duì)象支持與數(shù)學(xué)集合理論對(duì)應(yīng)的操作。按照定義,一個(gè)元素在集合中只能出現(xiàn)一次,不管它被添加了多少次。

因?yàn)榧鲜瞧渌麑?duì)象的集合體,因此它具有列表和字典這樣的對(duì)象的某些共同行為。例如,集合是可迭代對(duì)象,可以按需增長(zhǎng)或縮短,并且可以包含多種對(duì)象類型。一個(gè)集合的行為很像一個(gè)有鍵無(wú)值的字典,不過(guò)集合還支持更多的操作。

然而,由于集合是無(wú)序的,而且不會(huì)把鍵映射到值,因此它們既不是序列也不是映射類型;它們是自成一體的類型。

集合基礎(chǔ)知識(shí)

要?jiǎng)?chuàng)建一個(gè)集合對(duì)象,可以向內(nèi)置的 set 函數(shù)傳入一個(gè)序列或其他可迭代對(duì)象:

>>> x = set('abcde')
>>> y = set('bdxyz')
>>> x
{'b', 'd', 'c', 'a', 'e'}
>>> y
{'z', 'd', 'x', 'y', 'b'}

要注意集合并不包含位置順序——它們的順序是任意的,且可能隨 Python 版本而變化。

集合通過(guò)表達(dá)式運(yùn)算符支持一般的數(shù)學(xué)集合運(yùn)算。要注意,不能對(duì)諸如字符串、列表和元組的一般序列使用下面的運(yùn)算。

>>> x - y
{'a', 'c', 'e'}
>>> x | y
{'e', 'a', 'y', 'b', 'z', 'c', 'x', 'd'}
>>> x & y
{'b', 'd'}
>>> x ^ y
{'e', 'a', 'y', 'z', 'c', 'x'}
>>> x > y,x < y
(False, False)

該規(guī)則很明顯的一個(gè)例外就是集合成員測(cè)試 in。in 表達(dá)式也定義為可以在全部其他集合體類型上工作,其作用也是進(jìn)行成員測(cè)試。

>>> 'e' in x
True
>>> 'e' in 'Camelot', 22 in [11,22,33]
(True, True)

集合對(duì)象還提供了一些方法來(lái)支持集合的修改:add 方法插入一個(gè)項(xiàng)目,update 方法在原位置求并集,remove 根據(jù)值刪除一個(gè)元素。并且作為可迭代的容器,集合也可以用于 len,for 循環(huán)和列表推導(dǎo)這樣的操作。然而,由于集合是無(wú)序的,所以不支持像索引和分片這樣的操作。

>>> z = x.intersection(y)
>>> z
{'b', 'd'}
>>> z.add('SPAM')
>>> z
{'b', 'SPAM', 'd'}
>>> z.update(set(['x','Y']))
>>> z
{'SPAM', 'b', 'x', 'Y', 'd'}
>>> z.remove('b')
>>> z
{'SPAM', 'x', 'Y', 'd'}
>>> for item in set('abc'): print(item*3)
... 
aaa
ccc
bbb
>>> len(z)
4

注意,盡管前面介紹的集合表達(dá)式通常需要兩個(gè)集合,但它們基于方法的對(duì)應(yīng)形式往往可以對(duì)任何可迭代類型有效。

>>> S = set([1,2,3])
>>> S | set([3,4])
{1, 2, 3, 4}
>>> S | [3,4]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'set' and 'list'
>>> S.union([3,4])
{1, 2, 3, 4}
>>> S.intersection((1,3,5))
{1, 3}
>>> S.issubset(range(-5,5))
True
不可變性限制與凍結(jié)集合

集合有一個(gè)限制要記?。?strong>集合只能包含不可變的(可哈?;模?duì)象類型。因此,列表和字典不能嵌入集合中,元組是可以嵌入集合的。

>>> S
{1, 2, 3}
>>> S.add([1,2,3,4])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> S.add({'a':1})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'dict'
>>> S.add((1,2,3))
>>> S
{1, 2, 3, (1, 2, 3)}
>>> S | {(1,2,3),(4,5,6)}
{1, 2, 3, (1, 2, 3), (4, 5, 6)}
>>> S
{1, 2, 3, (1, 2, 3)}
>>> (1,2,3) in S
True
>>> (1,4,3) in S
False
>>> (1,2) in S
False

集合可以包含模塊、類型對(duì)象等。集合本身也是可變的,因此,不能直接嵌入其他集合中;如果要在另一個(gè)集合中存儲(chǔ)一個(gè)集合,可以像調(diào)用 set 一樣調(diào)用內(nèi)置函數(shù) frozenset,但 frozenset 會(huì)創(chuàng)建一個(gè)不可變的集合,該集合不可修改,并且可以嵌套到其他集合中。

集合推導(dǎo)

集合推導(dǎo)表達(dá)式類似于列表推導(dǎo)的形式。集合推導(dǎo)會(huì)運(yùn)行一個(gè)循環(huán)并在每次迭代時(shí)收集一個(gè)表達(dá)式的結(jié)果,通過(guò)一個(gè)循環(huán)變量來(lái)訪問(wèn)當(dāng)前的迭代值以用于集合表達(dá)式中。其結(jié)果就是通過(guò)運(yùn)行代碼創(chuàng)建了一個(gè)新的集合,它具備所有一般的集合行為。

>>> {x ** 2 for x in [1,2,3,4]}
{16, 1, 4, 9}
>>> {x for x in 'spam'}
{'a', 's', 'm', 'p'}
>>> {c * 4 for c in 'spam'}
{'pppp', 'ssss', 'aaaa', 'mmmm'}
>>> S = {c * 4 for c in 'spam'}
>>> S | {'mmmm','xxxx'}
{'xxxx', 'pppp', 'mmmm', 'ssss', 'aaaa'}
>>> S & {'mmmm','xxxx'}
{'mmmm'}
集合使用實(shí)例

由于項(xiàng)在集合中只能存儲(chǔ)一次,因此集合可以用于過(guò)濾其他集合體的重復(fù)項(xiàng),注意,元素可能會(huì)在該過(guò)程中重新排序(因?yàn)榧贤ǔJ菬o(wú)序的)。

>>> L = [1,2,1,3,2,4,5]
>>> set(L)
{1, 2, 3, 4, 5}
>>> L = list(set(L))
>>> L
[1, 2, 3, 4, 5]
>>> list(set(['yy','cc','aa','xx','dd','aa']))
['yy', 'xx', 'aa', 'dd', 'cc']

集合也可以用于提取列表、字符串以及其他可迭代對(duì)象中的差異,只需轉(zhuǎn)換為集合從而獲得差異。

>>> set([1,3,5,7]) - set([1,2,4,5,6])
{3, 7}
>>> set('abcdefg') - set('abdghij')
{'e', 'c', 'f'}
>>> set('spam') - set(['h','a','m'])
{'s', 'p'}
>>> set(dir(bytes)) - set(dir(bytearray))
{'__getnewargs__'}
>>> set(dir(bytearray)) - set(dir(bytes))
{'append', '__imul__', 'extend', 'remove', 'copy', 'clear', 'insert', 'pop', '__delitem__', '__iadd__', '__setitem__', '__alloc__', 'reverse'}

也可以通過(guò)轉(zhuǎn)換成集合,借助集合進(jìn)行順序無(wú)關(guān)的等價(jià)性測(cè)試。這是因?yàn)轫樞蛟诩现胁⒉恢匾蓚€(gè)集合相等當(dāng)且僅當(dāng)兩個(gè)集合中的每一個(gè)元素都被另一個(gè)集合所包含,也就是說(shuō),撇開順序,每一個(gè)集合都是另一個(gè)集合的子集。

>>> L1,L2=[1,3,5,2,4],[2,5,3,4,1]
>>> L1 == L2
False
>>> set(L1)==set(L2)
True
>>> sorted(L1)==sorted(L2)
True

布爾型

可以這樣認(rèn)為,Python 的布爾類型(bool)本質(zhì)上是數(shù)值的,因?yàn)樗瑑蓚€(gè)值 True 和 False,而且就是整數(shù) 1 和 0 的定制版,只不過(guò)打印時(shí)有所不同。更正式的說(shuō),Python 有一個(gè)名為 bool 的顯式布爾數(shù)據(jù)類型,帶有 True 和 False 作為可用且預(yù)賦值的內(nèi)置名稱。在內(nèi)部,名稱 True 和 False 是 bool 的實(shí)例,而 bool 實(shí)際上是內(nèi)置整數(shù)類型 int 的子類(從面向?qū)ο蟮慕嵌葋?lái)看)。

>>> type(True)
<class 'bool'>
>>> isinstance(True,int)
True
>>> True == 1
True
>>> True is 1
False
>>> True or False
True
>>> True + 4
5
向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI