Python的字符编码,二进制、八进制、十进制、十六进制和emoji

在《Python的编码与解码初探》中,对Python的编码知识稍做了一点研究,本文再深入一些,将字符编码以及不同进制的关系梳理一下。

1. ASCII和Unicode编码

先来看看ASCII和Unicode编码的一个例子:

  • 字母A用ASCII编码是十进制的65,二进制的01000001
  • 字符0用ASCII编码是十进制的48,二进制的00110000,注意字符'0'和整数0是不同的;
  • 汉字已经超出了ASCII编码的范围,用Unicode编码是十进制的20013,二进制的01001110 00101101

Python使用chr() 内置函数创建单字符Unicode字符串,该函数采用整数,并返回长度为1的包含相应码位的Unicode字符串。反向操作是内置ord()函数,它使用一个字符的Unicode字符串并返回码位值。

>>> ord('A')
65
>>> ord('0')
48
>>> ord('中')
20013
>>> chr(65)
'A'
>>> chr(48)
'0'
>>> chr(20013)
'中'

ASCII编码是1个字节,而Unicode编码通常是2个字节,如果把ASCII编码的A用Unicode编码,只需要在前面补0就可以,因此,A的Unicode编码是00000000 01000001
Unicode编码比ASCII编码需要多一倍的存储空间,于是又有了“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。

字符ASCIIUnicodeUTF-8
A0100000100000000 0100000101000001
-01001110 0010110111100100 10111000 10101101

2. 二进制、八进制、十进制和十六进制之间的转换

上面可以看到,ord()函数获取的是字符的整数表示,为十进制。
当我们把以Unicode表示的str编码为bytes类型时,其输出是十六进制:

>>> '中'.encode('utf-8')
b'\xe4\xb8\xad'

而我们最终需要的是二进制的表达方式,于是这里就需要在不同的进制之间进行转换。

2.1 转十进制

Python使用内置的 int(x, base=10) 函数来进行十进制的转换,第一个参数是数字或字符串,第二个参数是说明该字符串是几进制的数,默认为十进制。

>>> int('0xe4', 16)
228
>>> int('01000001', 2)
65
>>> int('17', 8)
15

2.2 转十六进制

Python使用内置的 hex(x) 函数将十进制的整数转换为以小写0x开头的十六进制字符串。如需要转换二进制或八进制,需要先将其转换为十进制。

>>> hex(228)
'0xe4'
>>> hex(int('01000001', 2))
'0x41'

也可以通过以下方式来格式化十六进制的显示:

>>> '%#x' % 228, '%x' % 228, '%X' % 228
('0xe4', 'e4', 'E4')
>>> format(228, '#x'), format(228, 'x'), format(228, 'X')
>>> f'{228:#x}', f'{228:x}', f'{228:X}'

2.3 转二进制

Python使用内置的 bin(x) 函数将十进制的整数转换为以小写0b开头的二进制字符串。如需要转换八进制或十六进制,需要先将其转换为十进制。

>>> bin(3)
'0b11'
>>> format(3, '#b'), format(3, 'b')
('0b11', '11')
>>> f'{3:#b}', f'{3:b}'

2.4 转八进制

Python使用内置的 oct(x) 函数将十进制的整数转换为以小写0o开头的八进制字符串。如需要转换二进制或十六进制,需要先将其转换为十进制。

>>> oct(8)
'0o10'
>>> '%#o'% 8 , '%o' % 8
('0o10', '10')
>>> format(8, '#o'), format(8, 'o')
('0o10', '10')
>>> f'{8:#o}', f'{8:o}'

3. 二进制填充

当使用二进制来表示字符编码时,我们一般是用填充了0的八位数字(1个字节)来表示。这里可以使用Python的 f-string 来进行格式化:

>>> f"{3:08b}"
'00000011'

其中3是需要转换的数,08是以0来填充满8位,b是要转换为二进制。

对字符串,可以使用下面的方式来进行格式化:

>>> def make_bitseq(s: str) -> str:
...     if not s.isascii():
...             raise ValueError("ASCII only allowed")
...     return ' '.join(f"{ord(i):08b}" for i in s)

>>> make_bitseq("puran")
'01110000 01110101 01110010 01100001 01101110'

4. 输出Unicode字符

通过Unicode列表可知,标准的Unicode编码是U+0417这样的格式,在Python中,是需要改写成\u0417才能正确的识别并输出对应的字符。

>>> '\u0417'
'З'
>>> 'U+0417'
'U+0417'

5. Python中的emoji

在Unicode中,还包含emoji的编码,当直接输出其编码时,一般得不到我们想要的内容:

>>> '\u1F600'
'ὠ0'

在Python中使用emoji有两种方式:

  1. 通过emoji的Unicode编码来输出
  2. 借助emoji库并通过emoji的别名来输出

1. 通过emoji的Unicode编码
在通过emoji的Unicode编码来输出emoji时,需要对编码进行改造,将编码扩展为8位。比如,👍的Unicode编码为U+1F44D,在输出时需将其改造为\U0001F44D

>>> print('\U0001F44D')
👍

2. 借助emoji库:
emoji 库的安装很简单:pip install emoji --upgrade

>>> import emoji
>>> print(emoji.emojize("Python is :thumbs_up:"))
Python is 👍
>>> print(emoji.demojize("Python is 👍"))
Python is :thumbs_up:

这个列表列出了几乎所有的emoji及其名字:https://www.webfx.com/tools/emoji-cheat-sheet/,在使用时直接参考即可。

参考

  1. Unicode HOWTO 中文翻译
  2. Python字符串和编码
  3. Python 二进制,十进制,十六进制转换
  4. Unicode & Character Encodings in Python: A Painless Guide
  5. Python 每一天 (5.16) - Emoji 🤣
  • 10
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值