python进制间互相转换和编码形式解读(转载自用)

各种进制之间相互转化

int('0x17', 16) # 16进制转化为10进制  23
int('101010',2) # 二进制转化为10进制
bin(42) # 十进制转化为2进制  '0b101010'
oct(10) # 十进制转化为8进制'0o12'
hex(23) # 十进制转16进制 '0x17'

我们可以看到,转化为2/8/16进制都有自己专门的函数,他们都支持将10进制转化为各自进制数;
而10进制使用int加参数指定从多少进制转化而来。这样以10进制为中间变量就可以实现各个进制数之间的转化。
如果我们想看各种编码对应的二进制数是多少,十进制数是多少呢,要对b \u \x这样的东西进行处理。
首先,看unicode的16/10/2进制对应数值

s = "中文"
" ".join("{:02x}".format(ord(c)) for c in s) # 16进制 '4e2d 6587'
" ".join("{:d}".format(ord(c)) for c in s) # 10进制   '20013 25991'
" ".join("{:b}".format(ord(c)) for c in s) # 二进制   '100111000101101 110010110000111'

上面代码的原理是

循环中的每个c对应’\u4e2d\u6587’中的\u4e2d和\u6587 ord是可以将\u前缀的16进制数识别出来并转化为8进制数
用format再将八进制数指定格式输出成16进制数,这两步相当于去掉了\u join将得到的16进制值用空格拼在一起
下面转化为10进制、二进制只是把format输出格式换了

另外,反向过程也是可以的,对于单个字符的正逆过程如下

ord('中') # 20013
chr(20013) # '中'

其次,看utf-8的16/10/2进制对应数值

utf-8中的bytes是三个\x表示一个文字,英文则是一个\x,所以没办法通过循环获知每一个字符的各进制数,只能得到整串字符的各个进制数(其实也是可以对每个字符分别解码再看的)

a = "中文"
b = a.encode('utf-8')
b.hex() # 'e4b8ade69687'
bin(int(b.hex(), 16)) # '0b111001001011100010101101111001101001011010000111'

因为两个十进制数拼起来和一起算结果不同,所以放在一起结果有误,只能分开看十进制结果

a = "中文"
for i in a:
    j = i.encode('utf-8')
    print(i,':')
    print(j.hex())
    print(int(j.hex(), 16))
    print(bin(int(j.hex(), 16)))
# 输出
# 中 :
# e4b8ad
# 14989485
# 0b111001001011100010101101
# 文 :
# e69687
# 15111815
# 0b111001101001011010000111

这是UTF-8的,因为GBK结果类似,所以用相同的代码就可以。

4.英文编码

我们继续来看最开始那些编码和解码的代码,可以发现一个比较奇怪的现象,即中文转化为UTF-8的编码是用16进制数表示的,而英文竟然直接用英文字母表示。这是因为英文在各个编码方式中对应的16进制数都是一样的(因为众多编码都兼容ASCII编码),比如’A’无论在ASCII、UTF-8还是GBK中对应的数字都是65,转化为16进制数也是一样,所以在Python中干脆将这些ASCII码对应的16进制值以ASCII码对应符号命名。我们可以用上一部分的方法探究英文字母的真实16进制值

a = "AB"
for i in a:
    j = i.encode('utf-8')
    print(i,':')
    print(j.hex())
    print(int(j.hex(), 16))
    print(bin(int(j.hex(), 16)))
# 输出
# A :
# 41
# 65
# 0b1000001
# B :
# 42
# 66
# 0b1000010

我们发现A的16进制值是41,B是42,用bytes形式在Python中输出如下

>>> m = b'\x41\x42'
>>> m
b'AB'

确实这些16进制都被字母代替了

编码的形式解读

首先要熟悉python中出现的编码形式,有时可以根据它的形式来判断这是什么编码
‘\u4e2d\u6587’就是中文二字对应的Unicode编码
b’\xe4\xb8\xad\xe6\x96\x87’就是中文二字对应的utf-8编码
b’\xd6\xd0\xce\xc4’就是中文二字对应的gbk编码

其中\u和\x都是转义字符,和\n换行符类似
\x表示十六进制数,每个\x后面跟两位,每一位都是0-9abcdef这16个中的一个。两位共可以表示16*16=256个数,即可以表示2^8=2568位的二进制数可以表示的数。也就是说一个\x可以代表一个字节

\u表示Unicode编码,一个\u后面接4位的16进制数,每一位也是0-9abcdef这16个中的一个,4位可以表示16位二进制数可以表示的数,所以说一个\u可以代表两个字节

从字节的角度我们再来看一下这个输出,“中文”两个字
在Unicode编码中占4个字节
在utf-8编码中占6个字节
在gbk编码中占4个字节
这个结果和我们之前所说的一个中文字符在各个编码中占字节数相符

再注意到’\u4e2d\u6587’直接输出和print都会出现“中文”二字,进一步说明python3中我们通常说的字符其实就是Unicode,将他们看成完全一样的就好
输出’\u4e2d\u6587’这种转义字符时,是识别了\u,自动通过对照表将后面的那串字节显示成了中文
对于b’'这种前面有个b的,type都变了,不是str而是bytes,这种在print时会原样输出

参考链接:
https://zhuanlan.zhihu.com/p/33220501

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值