接下來(lái)將學(xué)到很多操作數(shù)據(jù)的方法如输,它們大多與下面這兩種內(nèi)置的python數(shù)據(jù)類(lèi)型有關(guān)。
- 字符串 Unicode字符組成的序列挽封,用于存儲(chǔ)文本數(shù)據(jù)
- 字節(jié)和字節(jié)數(shù)組 8比特整數(shù)組成的序列穿挨,用于存儲(chǔ)二進(jìn)制數(shù)據(jù)
文本字符串
格式化
我們可以使用不同的格式化方法將變量插值(interpolate)到字符串中逊拍,即將變量的值嵌入字符串中郭脂。Python 有兩種格式化字符串的方式,我們習(xí)慣簡(jiǎn)單地稱之為舊式(old style)和新式(new style)。這兩種方式在 Python 2 和 Python 3 中都適用(新式格式化方法適用于 Python 2.6 及 以上)
使用%的舊式格式化
舊式格式化的形式為 string % data 鳄袍。其中string包含的是待插值的序列。下面是一些
簡(jiǎn)單的插值序列吏恭,它僅由%以及一個(gè)用于指定數(shù)據(jù)類(lèi)型的字母組成拗小。
轉(zhuǎn)換類(lèi)型:
%s 字符串
%d 十進(jìn)制整數(shù)
%x 十六進(jìn)制整數(shù)
%o 八進(jìn)制整數(shù)
%f 十進(jìn)制浮點(diǎn)數(shù)
%e 以科學(xué)計(jì)數(shù)法表示的浮點(diǎn)數(shù)
%g 十進(jìn)制或科學(xué)計(jì)數(shù)法表示的浮點(diǎn)數(shù)
%% 文本值%本身
首先格式化一個(gè)整數(shù):
栗子們:
In [1]: '%s' % 42
Out[1]: '42'
In [2]: '%d' % 42
Out[2]: '42'
In [3]: '%x' % 42
Out[3]: '2a'
In [4]: '%o' % 42
Out[4]: '52'
接著格式化浮點(diǎn)數(shù):
In [5]: '%s' % 7.03
Out[5]: '7.03'
In [6]: '%f' % 7.03
Out[6]: '7.030000'
In [7]: '%e' % 7.03
Out[7]: '7.030000e+00'
In [8]: '%g' % 7.03
Out[8]: '7.03'
整數(shù)和字面值%
In [9]: '%d%%' % 100
Out[9]: '100%'
關(guān)于字符串和整數(shù)的插值操作:
In [10]: actor = 'Richard Gere'
In [11]: cat = 'Chester'
In [12]: weight = 28
In [13]: "My wife's favorite actor is %s" % actor
Out[13]: "My wife's favorite actor is Richard Gere"
In [14]: "Our cat %s weighs %s pounds" % (cat,weight)
Out[14]: 'Our cat Chester weighs 28 pounds'
字符串內(nèi)的 %s 意味著需要插入一個(gè)字符串。字符串中出現(xiàn) % 的次數(shù)需要與 % 之后所提供的 數(shù)據(jù)項(xiàng)個(gè)數(shù)相同樱哼。如果只需插入一個(gè)數(shù)據(jù)哀九,例如前面的 actor剿配, 直接將需要插入的數(shù)據(jù)置于 % 后即可。如果需要插入多個(gè)數(shù)據(jù)阅束,則需要將它們封裝進(jìn)一個(gè)元組(以圓括號(hào)為界呼胚,逗號(hào) 分開(kāi)),例如上例中的 (cat, weight)息裸。
盡管 weight 是一個(gè)整數(shù)蝇更,格式化串中的 %s 也會(huì)將它轉(zhuǎn)化為字符串型。
我們可以在%和指定類(lèi)型的字母之間設(shè)定最大和最小寬度呼盆,排版以及填充字符等年扩。
我們來(lái)定義一個(gè)整數(shù) n、一個(gè)浮點(diǎn)數(shù) f 以及一個(gè)字符串 s:
n = 42
f = 7.03
s = 'string cheese'
使用默認(rèn)寬度格式化它們:
In [6]: '%d %f %s' % (n,f,s)
Out[6]: '42 7.030000 string cheese'
為每個(gè)變量設(shè)定最小域?qū)挒?0個(gè)字符访圃,右對(duì)齊厨幻,左側(cè)不夠用空格填:
In [7]: '%10d %10f %10s' % (n,f,s)
Out[7]: ' 42 7.030000 string cheese'
使用同樣的寬度,改為左對(duì)齊:
In [8]: '%-10d %-10f %-10s' % (n,f,s)
Out[8]: '42 7.030000 string cheese'
使用同樣同樣的域?qū)捦燔窃O(shè)定最大字符寬度為4克胳,右對(duì)齊。這樣的設(shè)置會(huì)截?cái)喑^(guò)長(zhǎng)度限制的字符串圈匆,并且將浮點(diǎn)數(shù)的精度限制在小數(shù)點(diǎn)后4位:
In [9]: '%10.4d %10.4f %10.4s' % (n,f,s)
Out[9]: ' 0042 7.0300 stri'
去掉域?qū)挒?0的限制:
In [10]: '%.4d %.4f %.4s' % (n,f,s)
Out[10]: '0042 7.0300 stri'
改變硬編碼方式漠另,將域?qū)挘址麑挾鹊仍O(shè)定作為參數(shù):
In [11]: '%*.*d %*.*f %*.*s' % (10,4,n,10,4,f,10,4,s)
Out[11]: ' 0042 7.0300 stri'
使用{}和format的新式格式化
新式格式化最簡(jiǎn)單的用法如下所示:
In [12]: '{} {} {}' .format(n,f,s)
Out[12]: '42 7.03 string cheese'
舊式格式化中傳入?yún)?shù)的順序需要與%占位符出現(xiàn)的順序完全一致跃赚,但在新式格式化里笆搓,可以自己指定插入的順序:
In [13]: '{2} {0} {1}' .format(n,f,s)
Out[13]: 'string cheese 42 7.03'
0代表第一個(gè)參數(shù)f;1代表字符串s纬傲;2代表最后一個(gè)參數(shù)满败,整數(shù)n。
參數(shù)可以是字典或者命名變量叹括,格式串中的標(biāo)示符可以引用這些名稱:
In [14]: '{n} {f} {s}' .format(n=42,f=7.03,s='string cheese')
Out[14]: '42 7.03 string cheese'
我們將之前作為參數(shù)的值存到一個(gè)字典中:
d = {'n': 42, 'f': 7.03, 's': 'string cheese'}
下面的栗子中算墨,{0}代表整個(gè)字典,{1}則代表字典后面的字符串'other'
In [15]: d = {'n': 42, 'f': 7.03, 's': 'string cheese'}
In [16]: '{0[n]} {0[f]} {0[s]} {1}' .format(d,'other')
Out[16]: '42 7.03 string cheese other'
上面這些例子都是以默認(rèn)格式打印結(jié)果的汁雷。舊式格式化允許在 % 后指定參數(shù)格式净嘀,但在新 式格式化里,將這些格式標(biāo)識(shí)符放在 : 后侠讯。
首先使用位置參數(shù)的例子:
In [18]: '{0:d} {1:f} {2:s}' .format(n,f,s)
Out[18]: '42 7.030000 string cheese'
接著是將參數(shù)改為命名參數(shù):
In [19]: '{n:n} {f:f} {s:s}' .format(n=42,f=7.03,s='string cheese')
Out[19]: '42 7.030000 string cheese'
新式格式化也支持其他各類(lèi)設(shè)置(最小域?qū)捦诓亍⒆畲笞址麑挕⑴虐嫦徜觯鹊龋?下面是最小域?qū)捲O(shè)為10膜眠,右對(duì)齊(默認(rèn))的栗子:
In [20]: '{0:10d} {1:10f} {2:10s}' .format(n,f,s)
Out[20]: ' 42 7.030000 string cheese'
使用 > 字符設(shè)定右對(duì)齊更為直觀:
In [21]: '{0:>10d} {1:>10f} {2:>10s}' .format(n,f,s)
Out[21]: ' 42 7.030000 string cheese'
最小域?qū)?0,左對(duì)齊:
In [22]: '{0:<10d} {1:<10f} {2:<10s}' .format(n,f,s)
Out[22]: '42 7.030000 string cheese'
最小域?qū)?0,居中
In [23]: '{0:^10d} {1:^10f} {2:^10s}' .format(n,f,s)
Out[23]: ' 42 7.030000 string cheese'
新式格式化與舊式格式化相比有一處明顯的不同:精度(precision宵膨,小數(shù)點(diǎn)后面的數(shù)字) 對(duì)于浮點(diǎn)數(shù)而言仍然代表著小數(shù)點(diǎn)后的數(shù)字個(gè)數(shù)架谎,對(duì)于字符串而言則代表著最大字符個(gè) 數(shù),但在新式格式化中你無(wú)法對(duì)整數(shù)設(shè)定精度:
In [24]: '{0:>10.4d} {1:>10.4f} {2:>10.4s}' .format(n,f,s)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-24-710b8b83231d> in <module>()
----> 1 '{0:>10.4d} {1:>10.4f} {2:>10.4s}' .format(n,f,s)
ValueError: Precision not allowed in integer format specifier
In [25]: '{0:>10d} {1:>10.4f} {2:>10.4s}' .format(n,f,s)
Out[25]: ' 42 7.0300 stri'
最后可以設(shè)定的值是填充字符柄驻。如果想要使用空格以外的字符進(jìn)行填充狐树,只需要把它放在 : 之后,其余任何排版符(<鸿脓,>抑钟,^)和寬度標(biāo)識(shí)符之前即可:
In [27]: '{0:!^20s}' .format('BIG SALE')
Out[27]: '!!!!!!BIG SALE!!!!!!'
使用正則表達(dá)式匹配
我們想要使用正則表達(dá)式(regular expression)必須先引用re模塊。我們需要定義一個(gè)用于匹配的模式(pattern)字符串以及一個(gè)匹配的對(duì)象:源(source)字符串野哭。簡(jiǎn)單的匹配在塔,如下所示:
In [1]: import re
In [2]: result = re.match('You','Young Frankenstein')
這里。'You'是模式拨黔,'Young Frankenstein' 是源——你想要檢查的字符串蛔溃。match()函數(shù)是用于查看源是否以模式開(kāi)頭。
對(duì)于更加復(fù)雜的匹配篱蝇,可以先對(duì)模式進(jìn)行編譯以加快匹配速度:
In [4]: youpattern = re.compile('You')
然后就可以之惡極使用編譯好的模式進(jìn)行匹配:
In [5]: result = youpattern.match('Young Frankenstein')
match()并不是比較source和pattern的唯一方法贺待。下面列出了其他的方法:
- search()會(huì)返回第一次匹配成功,如果存在的話零截。
- findall()會(huì)返回多有不重疊的匹配麸塞,如果存在的話。
- split()會(huì)根據(jù)pattern將source切片分成若干段涧衙,返回由這些片段組成的列表
- sub()還需要一個(gè)額外的參數(shù)replacement哪工,它會(huì)把source中所有匹配的pattern改成replacement。
1.使用match()進(jìn)行準(zhǔn)確匹配
字符串 'Young Frankenstein' 是以單詞 'You' 開(kāi)頭的嗎弧哎?以下是一些帶注釋的代碼:
In [1]: import re
In [2]: source = 'Young Frankenstein'
In [3]: m = re.match('You',source) #從源字符串的開(kāi)頭開(kāi)始匹配
In [4]: if m : # 匹配成功返回了對(duì)象雁比,將它輸出看看匹配得到的是什么
...: print(m.group())
...:
You
In [5]: m = re.match('^You',source) #起始錨點(diǎn)也能起到同樣作用
In [6]: if m:
...: print(m.group())
...:
You
嘗試匹配'Frank'會(huì)如何?
In [7]: m = re.match('Frank',source)
In [8]: if m:
...: print(m.group())
...:
這一次撤嫩,match() 什么也沒(méi)有返回偎捎,if 也沒(méi)有執(zhí)行內(nèi)部的 print 語(yǔ)句。如前所述序攘,match() 只能檢測(cè)以模式串作為開(kāi)頭的源字符串鸭限。但是 search() 可以檢測(cè)任何位置的匹配:
In [5]: m = re.search('Frank',source)
In [6]: if m:
...: print(m.group())
...:
Frank
改一下匹配模式:
In [7]: m = re.match('.*Frank',source)
In [8]: if m :
...: print(m.group())
...:
Young Frank
在上面的匹配模式中:
-
.
代表任意單一字符 -
*
代表任意一個(gè)它之前的字符,.*
代表任意多個(gè)字符(包括0個(gè)) - Frank是我們想要在源字符串中某處進(jìn)行匹配的短語(yǔ)两踏。
match() 返回了匹配 .*Frank 的字符串:'Young Frank'。
2.使用search()尋找首次匹配
我們可以使用search()在源字符'Young Frankenstein' 的任意位置尋找模式 'Frank'兜喻,無(wú) 需通配符 .*:
In [11]: m = re.search('Frank',source)
In [12]: if m: # search返回對(duì)象
...: print(m.group())
...:
Frank
3.使用findall()尋找所有匹配
之前的栗子都是查找到一個(gè)匹配就停止梦染。但是想要知道一個(gè)字符串中出現(xiàn)多少次字母'n'應(yīng)該怎么辦?
In [13]: m = re.findall('n',source)
In [14]: m # findall返回一個(gè)列表
Out[14]: ['n', 'n', 'n', 'n']
In [15]: print('Found',len(m),'matches')
Found 4 matches
將模式改為'n',緊跟著任意一個(gè)字符
In [16]: m = re.findall('n.',source)
In [17]: m
Out[17]: ['ng', 'nk', 'ns']
上面例子中最后一個(gè) 'n' 并沒(méi)有匹配成功帕识,需要通過(guò) ? 說(shuō)明 'n' 后面的字符是可 選的:
In [18]: m = re.findall('n.?',source)
In [19]: m
Out[19]: ['ng', 'nk', 'ns', 'n']
4.使用split()按匹配切分
下面的栗子展示了如何依據(jù)模式而不是簡(jiǎn)單的字符串(就像普通的split()方法做的)將一個(gè)字符串切分成由一系列子串組成的列表:
In [20]: m = re.split('n',source)
In [21]: m #split返回的列表
Out[21]: ['You', 'g Fra', 'ke', 'stei', '']
5.使用sub()替換匹配
這和字符串replace()方法有些類(lèi)似泛粹,只不過(guò)使用的是模式而不是文本串
In [22]: m = re.sub('n','?',source)
In [23]: m #sub返回的字符串
Out[23]: 'You?g Fra?ke?stei?'
6.模式:特殊的字符
我們已經(jīng)見(jiàn)過(guò)的一些基本模式:
- 普通的文本值代表自身,用于匹配非特殊字符
- 使用
*
表示任意多個(gè)字符串(包括0個(gè)) - 使用
?
表示可選字符(0個(gè)或1個(gè)) - 使用
.
代表任意除\n外的字符
下面是一些特殊字符
模式 匹配
\d 一個(gè)數(shù)字字符
\D 一個(gè)非數(shù)字字符
\w 一個(gè)字母或數(shù)字字符
\W 一個(gè)非字母或非數(shù)字字符
\s 空白符
\S 非空白符
\b 單詞邊界(一個(gè)\w與\W之間的范圍肮疗,順序可逆)
\B 非單詞邊界
Python 的 string 模塊中預(yù)先定義了一些可供我們測(cè)試用的字符串常量晶姊。我們將使用其中 的 printable 字符串,它包含 100 個(gè)可打印的 ASCII 字符伪货,包括大小寫(xiě)字母们衙、數(shù)字、空格 符以及標(biāo)點(diǎn)符號(hào)碱呼,下面我們將這一百個(gè)字符打印出來(lái):
In [24]: import string
In [25]: printable = string.printable
In [26]: len(printable)
Out[26]: 100
In [27]: printable[0:50]
Out[27]: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN'
In [28]: printable[50:]
Out[28]: 'OPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'
#printable 中哪些字符是數(shù)字蒙挑?
In [29]: re.findall('\d',printable)
Out[29]: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
#哪些字符是數(shù)字、字符或下劃線愚臀?
In [30]: re.findall('\w',printable)
Out[30]: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_']
#哪些屬于空格符忆蚀?
In [31]: re.findall('\s',printable)
Out[31]: [' ', '\t', '\n', '\r', '\x0b', '\x0c']
注意:正則表達(dá)式不僅僅適用于 ASCII 字符,例如 \d 還可以匹配 Unicode 的數(shù)字字符姑裂,并不 局 限 于 ASCII 中 的 '0' 到 '9'馋袜。
7.模式:使用標(biāo)識(shí)符
下面的模式標(biāo)識(shí)符中,expr和其他斜體的單詞表示合法的正則表達(dá)式舶斧。
模式標(biāo)識(shí)符:
模式 匹配
abc 文本值 abc
(expr) expr
expr1 | expr2 expr1 或 expr2
. 除 \n 外的任何字符
^ 源字符串的開(kāi)頭
$ 源字符串的結(jié)尾
prev? 0 個(gè)或 1 個(gè) prev
prev* 0 個(gè)或多個(gè) prev欣鳖,盡可能多地匹配
prev*? 0 個(gè)或多個(gè) prev,盡可能少地匹配
prev+ 1個(gè)或多個(gè) prev捧毛,盡可能多地匹配
prev+? 1 個(gè)或多個(gè) prev观堂,盡可能少地匹配
prev{m} m 個(gè)連續(xù)的 prev
prev{m, n} m 到 n 個(gè)連續(xù)的 prev,盡可能多地匹配
prev{m, n}? m 到 n 個(gè)連續(xù)的 prev呀忧,盡可能少地匹配
[abc] a 或 b 或 c(和 a|b|c 一樣)
[^abc] 非(a 或 b 或 c)
prev (?=next) 如果后面為 next师痕,返回 prev
prev (?!next) 如果后面非 next,返回 prev
(?<=prev) next 如果前面為 prev而账,返回 next
(?<!prev) next 如果前面非 prev胰坟,返回 next
先看一些小栗子:
In [1]: import re
首先定義我們使用的源字符串:
In [2]: source = '''I wish I may, I wish I might
...: Have a dish of fish tonight.'''
首先,在源字符串中檢索 wish:
In [3]: re.findall('wish',source)
Out[3]: ['wish', 'wish']
接著泞辐,對(duì)源字符串任意位置查詢 wish 或者 fish:
In [4]: re.findall('wish|fish',source)
Out[4]: ['wish', 'wish', 'fish']
從字符串開(kāi)頭開(kāi)始匹配 wish:
In [5]: re.findall('^wish',source)
Out[5]: []
從字符串開(kāi)頭開(kāi)始匹配 I wish:
In [6]: re.findall('^I wish',source)
Out[6]: ['I wish']
從字符串結(jié)尾開(kāi)始匹配 fish:
In [7]: re.findall('wish$',source)
Out[7]: []
最后笔横,從字符串結(jié)尾開(kāi)始匹配 fish tonight.:
In [8]: re.findall('fish tonight.$',source)
Out[8]: ['fish tonight.']
^ 和 $ 叫作錨點(diǎn)(anchor):^ 將搜索域定位到源字符串的開(kāi)頭,$ 則定位到末尾咐吼。上面例 子中的 .$ 可以匹配末尾的任意字符吹缔,包括句號(hào),因此能成功匹配锯茄。但更準(zhǔn)確地說(shuō)厢塘,上面 的例子應(yīng)該使用轉(zhuǎn)義符將 . 轉(zhuǎn)義為句號(hào)茶没,這才是我們真正想示意的純文本值匹配:
In [10]: re.findall('fish tonight\.$',source)
Out[10]: ['fish tonight.']
查詢以 w 或 f 開(kāi)頭,后面緊接著 ish 的匹配:
In [11]: re.findall('[wf]ish',source)
Out[11]: ['wish', 'wish', 'fish']
查詢以若干個(gè) w晚碾、s 或 h 組合的匹配:
In [12]: re.findall('[wsh]+',source)
Out[12]: ['w', 'sh', 'w', 'sh', 'h', 'sh', 'sh', 'h']
查詢以 ght 開(kāi)頭抓半,后面緊跟一個(gè)非數(shù)字非字母字符的匹配:
In [13]: re.findall('ght\W',source)
Out[13]: ['ght ', 'ght.']
查詢以 I 開(kāi)頭,后面跟著 wish 的匹配(wish 出現(xiàn)次數(shù)盡量少):
In [15]: re.findall('I (?=wish)',source)
Out[15]: ['I ', 'I ']
最后查詢以 wish 結(jié)尾格嘁,前面為 I 的匹配(I 出現(xiàn)的次數(shù)盡量少):
In [17]: re.findall('(?<=I) wish',source)
Out[17]: [' wish', ' wish']
有時(shí)笛求,正則表達(dá)式的語(yǔ)法可能會(huì)與 Python 本身的語(yǔ)法沖突。例如糕簿,我們期望下面例子中的 模式能匹配任何以 fish 開(kāi)頭的詞:
In [18]: re.findall('\bfish',source)
Out[18]: []
為什么沒(méi)有匹配成功探入?之前提到,Python 字符串會(huì)使用一些特殊的轉(zhuǎn)義符冶伞。例如上面 的 \b新症,它在字符串中代表退格,但在正則表達(dá)式中响禽,它代表一個(gè)單詞的開(kāi)頭位置徒爹。因此, 把 Python 的普通字符串用作正則表達(dá)式的模式串時(shí)需要特別注意芋类,不要像上面一樣與轉(zhuǎn)義 符產(chǎn)生沖突隆嗅。或者在任何使用正則表達(dá)式的地方都記著在模式串的前面添加字符r侯繁,這樣可以告訴Python這是一個(gè)正則表達(dá)式胖喳,從而禁用轉(zhuǎn)義符:
In [19]: re.findall(r'\bfish',source)
Out[19]: ['fish']
8.模式:定義匹配的輸出
當(dāng)使用match()或search()時(shí),所有的匹配會(huì)以m.group()的形式返回到對(duì)象m中贮竟。如果你用括號(hào)將某一模式包裹起來(lái)丽焊,括號(hào)中模式匹配的結(jié)果歸入到自己的group(無(wú)名稱)中,而調(diào)用m.groups()可以得到包含這些匹配的元組咕别,如下所示:
In [20]: m = re.search(r'(. dish\b).*(\bfish)',source)
In [21]: m.group()
Out[21]: 'a dish of fish'
In [22]: m.groups()
Out[22]: ('a dish', 'fish')
(?P< name >expr) 這樣的模式會(huì)匹配 expr技健,并將匹配結(jié)果存儲(chǔ)到名為 name 的組中:
In [23]: m = re.search(r'(?P<DISH>. dish\b).*(?P<FISH>\bfish)',source)
In [24]: m.group()
Out[24]: 'a dish of fish'
In [25]: m.groups()
Out[25]: ('a dish', 'fish')
In [26]: m.group(DISH)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-26-e95cb461ed66> in <module>()
----> 1 m.group(DISH)
NameError: name 'DISH' is not defined
In [27]: m.group('DISH')
Out[27]: 'a dish'
In [28]: m.group('FISH')
Out[28]: 'fish'
二進(jìn)制數(shù)據(jù)
處理二進(jìn)制數(shù)據(jù)我們需要了解像字節(jié)序(endianness,電腦處理器是如何將數(shù)據(jù)組織存儲(chǔ)為字節(jié)的)以及整數(shù) 的符號(hào)位(sign bit)之類(lèi)的概念惰拱。我們可能需要研究二進(jìn)制文件格式雌贱、網(wǎng)絡(luò)包等內(nèi)容,從而對(duì) 其中的數(shù)據(jù)進(jìn)行提取甚至修改偿短。本節(jié)將了解到 Python 中有關(guān)二進(jìn)制數(shù)據(jù)的一些基本操作欣孤。
字節(jié)和字節(jié)數(shù)組
Python3引入了下面兩種8比特序列存儲(chǔ)小整數(shù)的方式,每8比特可以存儲(chǔ)從0~255的值:
- 字節(jié)是不可變的昔逗,像字節(jié)數(shù)據(jù)組成的元組
- 字節(jié)數(shù)組是可變的降传,像字節(jié)數(shù)據(jù)組成的列表
我們的示例從創(chuàng)建列表 blist 開(kāi)始。接著需使用這個(gè)列表創(chuàng)建一個(gè) bytes 類(lèi)型的變量 the_ bytes 以及一個(gè) bytearray 類(lèi)型的變量 the_byte_array:
In [1]: blist = [1,2,3,255]
In [2]: the_bytes = bytes(blist)
In [3]: the_bytes
Out[3]: b'\x01\x02\x03\xff'
In [4]: the_byte_array = bytearray(blist)
In [5]: the_byte_array
Out[5]: bytearray(b'\x01\x02\x03\xff')
bytes 類(lèi)型值的表示形式比較特殊:以 b 開(kāi)頭勾怒,接著是一個(gè)單引號(hào)搬瑰,后面跟著
由十六進(jìn)制數(shù)(例如 \x02)或 ASCII碼組成的序列款票,最后以配對(duì)的單引號(hào)結(jié)束。
Python會(huì)將這些十六進(jìn)制數(shù)或者 ASCII碼轉(zhuǎn)換為整數(shù)泽论,如果該字節(jié)的值為有效
ASCII 編碼則會(huì)顯示 ASCII 字符。
In [6]: b'\x61'
Out[6]: b'a'
In [7]: b'\x01abc\xff'
Out[7]: b'\x01abc\xff'
下面的栗子說(shuō)明bytes類(lèi)型的不可變性和bytearray類(lèi)型的變量的可變性:
In [8]: the_bytes[1] = 127
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-8-8a3aebe74d04> in <module>()
----> 1 the_bytes[1] = 127
TypeError: 'bytes' object does not support item assignment
In [9]: the_byte_array[1] = 127
In [10]: the_byte_array
Out[10]: bytearray(b'\x01\x7f\x03\xff')
下面兩行代碼都會(huì)創(chuàng)建一個(gè)包含256個(gè)元素的結(jié)果卡乾,包含0~255的所有值:
In [11]: the_byte = bytes(range(0,256))
In [12]: the_byte_array = bytearray(range(0,256))
打印bytes或bytearray數(shù)據(jù)時(shí)翼悴,Python會(huì)以\xxx的形式表示不可打印的字符,以ASCII字符的形式表示可打印的字符(以及一些轉(zhuǎn)義字符幔妨,例如\n而不是\x0a)鹦赎。下面是the_byte的打印結(jié)果:
In [13]: the_byte
Out[13]: b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff'
看起來(lái)可能有些困惑,畢竟上面輸出的數(shù)據(jù)是字節(jié)(小整數(shù))而不是字符误堡。