Python學(xué)習(xí)筆記(八)Python操作數(shù)據(jù)

接下來(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ù))而不是字符误堡。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末古话,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子锁施,更是在濱河造成了極大的恐慌陪踩,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悉抵,死亡現(xiàn)場(chǎng)離奇詭異肩狂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)姥饰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)傻谁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人列粪,你說(shuō)我怎么就攤上這事审磁。” “怎么了岂座?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵态蒂,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我掺逼,道長(zhǎng)吃媒,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任吕喘,我火速辦了婚禮赘那,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘氯质。我一直安慰自己募舟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布闻察。 她就那樣靜靜地躺著拱礁,像睡著了一般琢锋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呢灶,一...
    開(kāi)封第一講書(shū)人閱讀 51,198評(píng)論 1 299
  • 那天吴超,我揣著相機(jī)與錄音,去河邊找鬼鸯乃。 笑死鲸阻,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的缨睡。 我是一名探鬼主播鸟悴,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼奖年!你這毒婦竟也來(lái)了细诸?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤陋守,失蹤者是張志新(化名)和其女友劉穎震贵,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體嗅义,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡屏歹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了之碗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝙眶。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖褪那,靈堂內(nèi)的尸體忽然破棺而出幽纷,到底是詐尸還是另有隱情,我是刑警寧澤博敬,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布友浸,位于F島的核電站,受9級(jí)特大地震影響偏窝,放射性物質(zhì)發(fā)生泄漏收恢。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一祭往、第九天 我趴在偏房一處隱蔽的房頂上張望伦意。 院中可真熱鬧,春花似錦硼补、人聲如沸驮肉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)离钝。三九已至票编,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卵渴,已是汗流浹背慧域。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浪读,地道東北人吊趾。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瑟啃,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揩尸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 第5章 引用類(lèi)型(返回首頁(yè)) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類(lèi)型 使用基本類(lèi)型...
    大學(xué)一百閱讀 3,233評(píng)論 0 4
  • python學(xué)習(xí)筆記 聲明:學(xué)習(xí)筆記主要是根據(jù)廖雪峰官方網(wǎng)站python學(xué)習(xí)學(xué)習(xí)的蛹屿,另外根據(jù)自己平時(shí)的積累進(jìn)行修正...
    renyangfar閱讀 3,043評(píng)論 0 10
  • http://python.jobbole.com/85231/ 關(guān)于專業(yè)技能寫(xiě)完項(xiàng)目接著寫(xiě)寫(xiě)一名3年工作經(jīng)驗(yàn)的J...
    燕京博士閱讀 7,574評(píng)論 1 118
  • 曾經(jīng)一直覺(jué)得二十幾歲是很長(zhǎng)很長(zhǎng)的错负,長(zhǎng)到好像沒(méi)有那么快過(guò)去一樣∮卤撸或者說(shuō)犹撒,至少二十幾歲,和我們生命中的任何一個(gè)十年一樣...
    小魚(yú)1989閱讀 458評(píng)論 0 0
  • 早上起來(lái)發(fā)現(xiàn)淘寶上花一百塊錢(qián)買(mǎi)的暖風(fēng)機(jī)壞了粒褒,當(dāng)時(shí)我還特地拍照返現(xiàn)了十元识颊,結(jié)果就變成一個(gè)不到一百塊的東西壞了。附近一...
    達(dá)西小姐閱讀 383評(píng)論 0 0