Unicode
!!!个人主页:个人主页
!!!推荐一款模拟面试、刷题神器,从基础到大厂面试题:点击此处进入牛客网注册学习吧
!!!今日的努力,明日的未来
两种表示字符序列的类型:bytes
和str
。前者实例包括原始的8位值(就是原始的字节,由于美俄字节有8个二进制位,就是原始的8位值),后者的实例包含Unicode字符
文本字符串
utf-8——>可变长 1个字节时(0_ _ _ _ _ _ _ )2个字节时(110_ _ _ _ _ 10_ _ _ _ _ _ )3个字节(1110 _ _ _ _ 10_ _ _ _ _ 10 _ _ _ _ )4个字节(11110 _ _ 10 _ _ _ _ _ _ 10 _ _ _ _ _ 10_ _ _ _ _ _ )
‘你’——20320D——4F60H——0100 1111 0110 0000B(码点)——11100100 10111101 10100000(UTF-8)(b’E4BDA0’ = b’\xE4\xBD\xA0’)
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 解码<<<<_ _ _ _ _ _ _ _ _ _ >>>>编码 _ _ _ _ _ _ _ _ _ _ |
在python3当中,字符串是由一系列Unicode码位所组成的不可变序列
通过某个字符的Unicode ID,可以直接获得其对应的字符。
- 用
\u
及4个十六进制的数字从Unicode256个基本多语言中指定某一特定的字符。其中,前两个十六进制数字用于指定平面号(00—FF),后面两个数字用于指定该字符在平面上的位置索引 - 使用更多的比特位来储存位于更高平面的字符。Python使用以
\U
开头的转义序列来处理,后面跟紧8个十六进制的数字,其中最左一位需为0 - 使用
\N{name}
来引用某一字符,其中name为该字符的标准名称,这时所有平面的字符都适用
两个方向的转换函数:
lookup()
接收不区分大小的标准名称,返回一个Unicode字符name()
接收一个Unicode字符,返回大写形式的名称- ord()`输出对应字符的十进制(码位)
- 用len()可计算Unicode字符的个数
编码与解码
编码:encode()
解码:decode()
print('🐣'.encode())
print('你'.encode().decode())
#b'\xf0\x9f\x90\xa3'
#你
码位:字符集中字符所储存的位置(或者说对于的计算机通用的数字)
ASCII只需要一个字节就能存下来,而Unicode通常需要几个字节
UTF—8动态编码方式:
- 为ASCII字符分配1字节
- 为拉丁语系得语言分配2字节
- 为其他的位于基本多语言的字符分配3字节(包含中文在内的CJK)
- 剩下的都是分配4字节
在解码的时候我们要知道用何种方式进行编码的,这样才能正确解码
实践中的策略:
- 记清楚编码与解码的方向
- 在python中的操作尽量采用UTF-8,输入或输出的时候再根据需求确定是否需要编码成二进制
在编写Python程序时,一定要把编码和解码操作放在界面最外围来做。程序的核心部分应该使用Unicode字符类型,而且不要对字符编码做任何假设,这种办法既可以令程序接受多种类型的文本编码,又可以保证输出文本信息只采用一种编码形式
所以Python代码中经常会出现:
- 开发者需要原始8位值,这些8位值表示以UTF-8格式来编码
- 开发者需要操作没有特定编码形式的Unicode字符
一般我i们会编写两个辅助函数,以便在这两种情况中进行转换,第一个函数接收str或bytes,并总是返回str
def to_str(bytes_or_str, encoding='utf-8'):
if isinstance(bytes_or_str, bytes):
value = bytes_or_str.decode(encoding)
else:
value = bytes_or_str
return value # instance of str
第二个函数接收str或bytes,并总是返回bytes
def to_bytes(bytes_or_str):
if isinstance(bytes_or_str, str):
value = bytes_or_str.encode('utf-8')
else:
value = bytes_or_str
return value # instance of bytes
二进制数据
-
字节和字节数组
字节(bytes),不可变。字节数组(bytearray),不可变
blist = [1, 2, 3, 255] the_bytes = bytes(blist) the_bytes # b'\x01\x02\x03\xff' the_byte_array = bytearray(blist) the_byte_array # bytearray(b'\x01\x02\x03\xff')
-
bytes类型值得表示:以b开头,接着是
'
后面跟着由16进制数。如果是ASCII码则显示ASCII字符
格式化
如果使用不同格式方法将变量插值到字符串中,即将变量得值嵌入到字符串中
-
使用
%
进行格式话
如string%data
.其中string
是待插值得序列:类型 意义 %s 字符串 %d 十进制数 %x 十六进制数 %o 八进制数 %f 十进制数 %e 以科学计数法表示的浮点数 %g 十进制或科学计数法表示的浮点数 %% 文本值%本身
字符串中出现%个数要与%之后所提供得数据项地个数相同。如果需要插入多个数据,就需要将他们放入同一个元组。
另外,可以在%和指定类型地字母之间设定最大和最小宽度、排版以及填充字符等
n = 42
f = 7.03
s = 'string cheese'
# 以默认宽度格式化
'%d %f %s' % (n, f, s) # '42 7.030000 string cheese' 封装成元组
# 最小域宽10个字符,右对齐,左侧不够空格填充
'%10d %10f %10s' % (n, f, s) # ' 42 7.030000 string cheese'
# 将上例 ⬅️对齐
'%-10d %-10f %-10s' % (n, f, s) # '42 7.030000 string cheese'
# 将上例 ➡️对齐,最大字符宽度为4
'%10.4d %10.4f %10.4s' % (n, f, s) # ' 0042 7.0300 stri'
# 去掉最小域宽为10的限制
'%.4d %.4f %.4s' % (n, f, s) # '0042 7.0300 stri'
# 将域宽、字符宽度等设定为参数
'%*.*d %*.*f %*.*s' % (10, 4, n, 10, 4, f, 10, 4, s)
# ' 0042 7.0300 stri'
-
使用{}和format格式化
n = 42 f = 7.03 s = 'string cheese' '{} {} {}'.format(n, f, s) # '42 7.03 string cheese' # 指定插入的顺序,传入的是元素的下标 '{2} {0} {1}'.format(f, s, n) # '42 7.03 string cheese' # 参数为字典或命名变量,格式串中标识符可以引用这些名称 '{n} {f} {s}'.format(n=42, f=7.03, s='string cheese') # '42 7.03 string cheese' d = dict(n=42, f=7.03, s='string cheese') # {'f': 7.03, 'n': 42, 's': 'string cheese'} # {0} 代表整个字典,{1}代表字典后面的字符串'other' '{0[n]} {0[f]} {0[s]} {1}'.format(d, 'other') # '42 7.03 string cheese other' #将格式标识符放在:之后,:前面表示地是format后面的()中的位置 '{0:d} {1:f} {2:s}'.format(n, f, s) # '42 7.030000 string cheese' '{n:d} {f:f} {s:s}'.format(n=42, f=7.03, s='string cheese') # '42 7.030000 string cheese' # 最小域宽设为10、右对齐 '{0:10d} {1:10f} {2:10s}'.format(n, f, s) # ' 42 7.030000 string cheese' # 使用 > 设定右对齐 '{0:>10d} {1:>10f} {2:>10s}'.format(n, f, s) # ' 42 7.030000 string cheese' # 左对齐 '{0:<10d} {1:<10f} {2:<10s}'.format(n, f, s) # '42 7.030000 string cheese' # 居中 '{0:^10d} {1:^10f} {2:^10s}'.format(n, f, s) ' 42 7.030000 string cheese'