Python中int、str、bytes相互转化,还有2进制、16进制表示,你想要的都在这里了
文章目錄
- 前言
- 數(shù)據(jù)類(lèi)型轉(zhuǎn)化
- int -> str
- 使用 str() 函數(shù)
- 使用 format() 函數(shù)
- 使用 hex() 轉(zhuǎn)換成16進(jìn)制形式
- 使用 bin() 轉(zhuǎn)換成2進(jìn)制形式
- str -> int
- 使用 int() 進(jìn)行各進(jìn)制數(shù)字轉(zhuǎn)換
- 什么是bytes
- int -> bytes
- 使用 to_bytes() 轉(zhuǎn)換成定長(zhǎng)bytes
- 使用 bytes() 函數(shù)把int數(shù)組轉(zhuǎn)成bytes
- 使用 struct.pack() 函數(shù)把數(shù)字轉(zhuǎn)化成bytes
- bytes -> int
- 使用 from_bytes() 把 bytes 轉(zhuǎn)化成int
- 使用 struct.unpack() 把 bytes 轉(zhuǎn)化成int
- str 和 bytes
- 使用 encode() 函數(shù)完成 str -> bytes
- 使用 decode() 函數(shù)完成 bytes -> str
- 假如使用了 str() 函數(shù)
- 轉(zhuǎn)化表格
- 總結(jié)
前言
數(shù)據(jù)類(lèi)型轉(zhuǎn)換是個(gè)很基礎(chǔ)的操作,很多語(yǔ)言中都要做這些轉(zhuǎn)換,例如前一段時(shí)間剛剛總結(jié)了《C/C++中string和int相互轉(zhuǎn)換的常用方法》,python 自從分離出 python3 版本之后,str 和 bytes 兩個(gè)類(lèi)型弄蒙了一大票人,在這兩種類(lèi)型的轉(zhuǎn)換上我可是花了不少時(shí)間,記住一點(diǎn),別隨隨便便使用 str() 函數(shù),很多數(shù)據(jù)使用 str() 變成字符串之后再想恢復(fù)可就難了。
本文所有示例均在 Python 3.7.5 上測(cè)試,Python2 已經(jīng)被我拋棄了,我來(lái)試著把常見(jiàn)的轉(zhuǎn)換都放到一起,把踩過(guò)的坑拿來(lái)開(kāi)心一下,如果有些常用的類(lèi)型轉(zhuǎn)換這里沒(méi)有的話(huà),也歡迎小伙伴們提出來(lái),我將持續(xù)補(bǔ)充,好了,可以開(kāi)始了。
數(shù)據(jù)類(lèi)型轉(zhuǎn)化
數(shù)字中除了整數(shù),還有浮點(diǎn)數(shù)、復(fù)數(shù)等,但是 int 是最常見(jiàn)的類(lèi)型,所有轉(zhuǎn)換中的數(shù)字只涉及 int 數(shù)字類(lèi)型。
int -> str
使用 str() 函數(shù)
num = 10 val = str(10) print(type(val), val)#<class 'str'> 10使用 format() 函數(shù)
num = 10 val = '{0}'.format(num) print(type(val), val)#<class 'str'> 10使用 hex() 轉(zhuǎn)換成16進(jìn)制形式
num = 10 val = hex(num) print(type(val), val)#<class 'str'> 0xa使用 bin() 轉(zhuǎn)換成2進(jìn)制形式
num = 10 val = bin(num).replace('0b','') print(type(val), val)#<class 'str'> 1010str -> int
這個(gè)轉(zhuǎn)換比較專(zhuān)一,只使用 int() 函數(shù)就可以了,這個(gè)函數(shù)實(shí)際上有兩個(gè)參數(shù),第二個(gè)參數(shù)表示進(jìn)制,默認(rèn)是10進(jìn)制,你可以改成2進(jìn)制或者16進(jìn)制,甚至是3進(jìn)制、5進(jìn)制等等
使用 int() 進(jìn)行各進(jìn)制數(shù)字轉(zhuǎn)換
val = int('10') print(type(val), val)val = int('0xa', 16) print(type(val), val) val = int('a', 16) print(type(val), val)val = int('0b1010', 2) print(type(val), val) val = int('1010', 2) print(type(val), val)val = int('101', 3) print(type(val), val)val = int('60', 5) print(type(val), val)# 結(jié)果均為 <class 'int'> 10使用 int() 函數(shù)的時(shí)候要主要注意一點(diǎn),如果提供的字符串不能轉(zhuǎn)換成指定進(jìn)制的數(shù)字,那么會(huì)報(bào)異常,就像下面這樣,所以在使用這個(gè)函數(shù)的時(shí)候最好放到 try 語(yǔ)句中。
val = int('128', 2)''' Traceback (most recent call last):File "D:\python\convert\convert.py", line 41, in <module>val = int('128', 2) ValueError: invalid literal for int() with base 2: '128' [Finished in 0.1s with exit code 1] '''什么是bytes
在列舉 bytes 相關(guān)的轉(zhuǎn)化前,我們來(lái)先認(rèn)識(shí)一下這個(gè)類(lèi)型,在 Python3 中 int、str、bytes 類(lèi)型的變量實(shí)際上都是一個(gè) “類(lèi)” 的對(duì)象,而 bytes 相比 str 而言更接近底層數(shù)據(jù),也更接近存儲(chǔ)的形式,它其實(shí)是一個(gè)字節(jié)的數(shù)組,類(lèi)似于 C 語(yǔ)言中的 char [],每個(gè)字節(jié)是一個(gè)范圍在 0-255 的數(shù)字。
bytes 其實(shí)就是這樣一連串的數(shù)字,計(jì)算機(jī)世界所有的信息都可以用這樣一串?dāng)?shù)字表示,一幅畫(huà),一首歌,一部電影等等,如果對(duì)編碼感興趣可以看看這篇《簡(jiǎn)單聊聊01世界中編碼和解碼這對(duì)磨人的小妖兒》,現(xiàn)在清楚bytes是什么了,我們可以看看和它相關(guān)的轉(zhuǎn)化了。
int -> bytes
使用 to_bytes() 轉(zhuǎn)換成定長(zhǎng)bytes
num = 4665 val = num.to_bytes(length=4, byteorder='little', signed=False) print(type(val), val)#<class 'bytes'> b'9\x12\x00\x00'這段代碼就是把數(shù)字 4665 轉(zhuǎn)化成定長(zhǎng)的4個(gè)字節(jié),字節(jié)序?yàn)樾《?#xff0c;我們來(lái)簡(jiǎn)單看一下是怎么轉(zhuǎn)換的:
上面我們提到 bytes 類(lèi)型一串 0-255 范圍的數(shù)字,4665 肯定超出了這個(gè)范圍,可以先轉(zhuǎn)化成256進(jìn)制,就變成了 <18><57>,也就是 4665 = 18 * 256 + 57,我們發(fā)現(xiàn)兩個(gè)字節(jié)就能存儲(chǔ)這個(gè)數(shù)字,一個(gè)18,一個(gè)57,要想組成4個(gè)字節(jié)的數(shù)組需要補(bǔ)充兩個(gè)空位,也就是補(bǔ)充兩個(gè)0,這時(shí)就涉及到一個(gè)排列順序,是 [0,0,18,57] 還是 [57, 18, 0, 0] 呢,這就是函數(shù)參數(shù)中的字節(jié)序 byteorder,little 表示小端,big 表示大端,這里選擇的小端 [57, 18, 0, 0] 的排列。
看到這里可能會(huì)迷糊,好像和結(jié)果不一樣啊,其實(shí)這只是一個(gè)表示問(wèn)題,57 的 ASCII 碼對(duì)應(yīng)這個(gè)字符 ‘9’,18 表示成16進(jìn)制就是 ‘0x12’,這里寫(xiě)成 b’9\x12\x00\x00’ 只是便于識(shí)別而已,實(shí)際上內(nèi)存存儲(chǔ)的就是 [57, 18, 0, 0] 這一串?dāng)?shù)字對(duì)應(yīng)的二進(jìn)制編碼 ‘00111001 00010010 00000000 00000000’。
使用 bytes() 函數(shù)把int數(shù)組轉(zhuǎn)成bytes
參考上面的生成的數(shù)組,可以通過(guò)數(shù)組生成相同的結(jié)果
num_array = [57, 18, 0, 0] val = bytes(num_array) print(type(val), val)#<class 'bytes'> b'9\x12\x00\x00'使用 struct.pack() 函數(shù)把數(shù)字轉(zhuǎn)化成bytes
num = 4665 val = struct.pack("<I", num) print(type(val), val)#<class 'bytes'> b'9\x12\x00\x00'這里的 "<I" 表示將一個(gè)整數(shù)轉(zhuǎn)化成小端字節(jié)序的4字節(jié)數(shù)組,其他的類(lèi)型還有:
| > | 大端序 |
| < | 小端序 |
| B | uint8類(lèi)型 |
| b | int8類(lèi)型 |
| H | uint16類(lèi)型 |
| h | int16類(lèi)型 |
| I | uint32類(lèi)型 |
| i | int32類(lèi)型 |
| L | uint64類(lèi)型 |
| l | int64類(lèi)型 |
| s | ascii碼,s前帶數(shù)字表示個(gè)數(shù) |
bytes -> int
明白了上面的轉(zhuǎn)化過(guò)程,從 bytes 轉(zhuǎn)化到 int 只需要反著來(lái)就行了
使用 from_bytes() 把 bytes 轉(zhuǎn)化成int
bys = b'9\x12\x00\x00' val = int.from_bytes(bys, byteorder='little', signed=False) print(type(val), val)#<class 'int'> 4665使用 struct.unpack() 把 bytes 轉(zhuǎn)化成int
bys = b'9\x12\x00\x00' val = struct.unpack("<I", bys) print(type(val), val)#<class 'tuple'> (4665,)str 和 bytes
前面的這些轉(zhuǎn)化還算清晰,到了字符串str 和字節(jié)串 bytes,就開(kāi)始進(jìn)入了混沌的狀態(tài),這里會(huì)出現(xiàn)各種編碼,各種亂碼,各種報(bào)錯(cuò),牢記一點(diǎn) str 到 bytes 是編碼過(guò)程,需要使用 encode() 函數(shù), bytes 到 str 是解碼過(guò)程,需要使用 decode() 函數(shù),請(qǐng)勿使用 str 函數(shù),否則后果自負(fù)。
使用 encode() 函數(shù)完成 str -> bytes
s = '大漠孤煙直qaq' val = s.encode('utf-8') print(type(val), val)# <class 'bytes'> b'\xe5\xa4\xa7\xe6\xbc\xa0\xe5\xad\xa4\xe7\x83\x9f\xe7\x9b\xb4qaq'使用 decode() 函數(shù)完成 bytes -> str
bys = b'\xe5\xa4\xa7\xe6\xbc\xa0\xe5\xad\xa4\xe7\x83\x9f\xe7\x9b\xb4qaq' val = bys.decode('utf-8') print(type(val), val)# <class 'str'> 大漠孤煙直qaq假如使用了 str() 函數(shù)
從上面來(lái)看字符串和字節(jié)串的轉(zhuǎn)化蠻簡(jiǎn)單的,甚至比整數(shù)的轉(zhuǎn)化都要簡(jiǎn)單,但是你如果把一個(gè) bytes 變量用 str() 轉(zhuǎn)化成字符串,你就得手動(dòng)來(lái)處理了,這個(gè)函數(shù)寫(xiě)過(guò)n次了,暫時(shí)還沒(méi)找到好的處理辦法。
bys = b'\xe5\xa4\xa7\xe6\xbc\xa0\xe5\xad\xa4\xe7\x83\x9f\xe7\x9b\xb4qaq' s = str(bys) print(type(s), s) #<class 'str'> b'\xe5\xa4\xa7\xe6\xbc\xa0\xe5\xad\xa4\xe7\x83\x9f\xe7\x9b\xb4qaq'def str2bytes(str_content):result_list = [];pos = 0str_content = str_content.replace("\\n", "\n").replace("\\t", "\t").replace("\\r", "\r")content_len = len(str_content)while pos < content_len:if str_content[pos] == '\\' and pos + 3 < content_len and str_content[pos + 1] == 'x':sub_str = str_content[pos + 2: pos + 4]result_list.append(int(sub_str, 16))pos = pos + 4else:result_list.append(ord(str_content[pos]))pos = pos + 1return bytes(result_list)val = str2bytes(s[2:-1]) print(type(val), val)# <class 'bytes'> b'\xe5\xa4\xa7\xe6\xbc\xa0\xe5\xad\xa4\xe7\x83\x9f\xe7\x9b\xb4qaq'什么時(shí)候會(huì)遇到這種情況,就是有些數(shù)據(jù)是以 bytes 的形式給的,但是經(jīng)過(guò)中間人復(fù)制轉(zhuǎn)發(fā)變成了字節(jié)流形式的字符串,格式還不統(tǒng)一,有些已經(jīng)翻譯成了字符,有些還保留了0x或者\(yùn)x形式,這時(shí)就要手工處理了。
轉(zhuǎn)化表格
上面的轉(zhuǎn)化方式和解釋穿插在一起有些亂,這里總結(jié)一個(gè)表格,便于今后拿來(lái)就用
| int | str | str(10)、'{0}'.format(10) | 10 => '10' |
| int | str(16進(jìn)制) | hex(10) | 10 => '0xa' |
| int | str(2進(jìn)制) | bin(10).replace('0b','') | 10 => '1010' |
| str | int | int('10') | '10' => 10 |
| str(16進(jìn)制) | int | int('0xa', 16) | '0xa' => 10 |
| str(2進(jìn)制) | int | int('1010', 2) | '1010' => 10 |
| int | bytes | num.to_bytes(length=4, byteorder='little', signed=False) | 4665 => b'9\x12\x00\x00' |
| int | bytes | struct.pack("<I", 4665) | 4665 => b'9\x12\x00\x00' |
| bytes | int | int.from_bytes(b'9\x12\x00\x00', byteorder='little', signed=False) | b'9\x12\x00\x00' => 4665 |
| bytes | int | struct.unpack("<I", b'9\x12\x00\x00') | b'9\x12\x00\x00' => 4665 |
| int[] | bytes | bytes([57, 18, 0, 0]) | [57, 18, 0, 0] => b'9\x12\x00\x00' |
| bytes | int[] | [x for x in b'9\x12\x00\x00'] | b'9\x12\x00\x00' => [57, 18, 0, 0] |
| str | bytes | '美好'.encode('utf-8') | '美好' => b'\xe7\xbe\x8e\xe5\xa5\xbd' |
| str | bytes | bytes('美好', 'utf-8') | '美好' => b'\xe7\xbe\x8e\xe5\xa5\xbd' |
| bytes | str | b'\xe7\xbe\x8e\xe5\xa5\xbd'.decode('utf-8') | b'\xe7\xbe\x8e\xe5\xa5\xbd' => '美好' |
| bytes | bytes(無(wú)\x) | binascii.b2a_hex(b'\xe7\xbe\x8eqaq') | b'\xe7\xbe\x8eqaq' => b'e7be8e716171' |
| bytes | bytes(有\(zhòng)x) | binascii.a2b_hex(b'e7be8e716171') | b'e7be8e716171' => b'\xe7\xbe\x8eqaq' |
| bytes | str(hex) | b'\xe7\xbe\x8eqaq'.hex() | b'\xe7\xbe\x8eqaq' => 'e7be8e716171' |
| str(hex) | bytes | bytes.fromhex('e7be8e716171') | 'e7be8e716171' => b'\xe7\xbe\x8eqaq' |
總結(jié)
- Python3 對(duì)字符串和二進(jìn)制數(shù)據(jù)流做了明確的區(qū)分,不會(huì)以任意隱式的方式混用 str 和 bytes
- bytes 類(lèi)型是一種比特流,它的存在形式是 01010001110 的形式,需要解碼成字符才容易被人理解
- struct 模塊中的 pack() 和 unpack() 可以實(shí)現(xiàn)任意類(lèi)型和 bytes 之間的轉(zhuǎn)換
- binascii.b2a_hex 和 binascii.a2b_hex 可以實(shí)現(xiàn)16進(jìn)制 bytes 的不同形式轉(zhuǎn)換,不過(guò)轉(zhuǎn)換前后長(zhǎng)度發(fā)生了變化
==>> 反爬鏈接,請(qǐng)勿點(diǎn)擊,原地爆炸,概不負(fù)責(zé)!<<==
初識(shí)不知曲中意,再聞已是曲中人
總結(jié)
以上是生活随笔為你收集整理的Python中int、str、bytes相互转化,还有2进制、16进制表示,你想要的都在这里了的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 震撼!世界从10亿光年到0.1飞米(ZT
- 下一篇: python量化交易笔记---13.描述