当前位置: 主页 > Python语言

python 编码成unicode-url编码和unicode编码

发布时间:2023-02-12 09:16   浏览次数:次   作者:佚名

字符编码

我们已经说过字符串也是一种数据类型,但是字符串的特殊之处在于存在编码问题。

因为计算机只能处理数字,所以如果要处理文本,必须先将文本转换为数字,然后才能处理。 最早的计算机在设计时使用8位(bit)作为一个字节(byte),所以一个字节所能表示的最大整数是255(二进制11111111=十进制255)python 编码成unicode,如果要表示更大的整数,就必须使用更多字节。 例如,两个字节可以表示的最大整数是65535,四个字节可以表示的最大整数是4294967295。

由于计算机是美国人发明的,最早只有127个字符被编码进计算机,即大小写的英文字母、数字和一些符号。 这种码表称为 ASCII 码。 例如大写字母A的编码为65.,小写字母z的编码为122。

但是要处理中文,一个字节显然是不够的,至少需要两个字节,而且不能和ASCII码冲突。 为此,我国制定了GB2312编码对中文进行编码。

你可以想象的是,世界上有数百种语言。 日本将日语编译成Shift_JIS,韩国将韩语编译成Euc-kr。 每个国家都有自己的标准,难免会发生冲突。 结果,在混合了多种语言的文本中,就会出现乱码显示。

char-encoding-problem

因此,Unicode字符集应运而生。 Unicode把所有的语言统一成一套编码,这样就不会再出现乱码了。

Unicode标准也在不断发展,但最常用的是UCS-16编码,用两个字节来表示一个字符(如果要用很远的字符,就需要4个字节)。 现代操作系统和大多数编程语言都直接支持 Unicode。

现在,我们来看看ASCII编码和Unicode编码的区别:ASCII编码是1个字节,而Unicode编码通常是2个字节。

字母A的ASCII码十进制为65,二进制为01000001;

字符0的ASCII编码十进制为48,二进制为00110000。 请注意,字符“0”与整数 0 不同;

汉字已经超出了ASCII编码的范围。 Unicode编码十进制为20013,二进制为1538729559661101。

可以猜想,如果ASCII编码的A是用Unicode编码的话,只需要在前面加0即可。 因此,A的Unicode编码为1538729559660001。

一个新的问题又出现了:如果统一成Unicode编码,乱码问题就没有了。 但是,如果你写的文字基本都是英文的话,使用Unicode编码需要的存储空间是ASCII编码的两倍,无论从存储还是传输上都是非常不经济的。

因此,本着节约的精神,出现了将Unicode编码转换为“变长编码”的UTF-8编码。 UTF-8编码将一个Unicode字符根据不同的数字大小编码成1-6个字节。 常用的英文字母编码为1个字节,汉字通常为3个字节。 只有非常罕见的字符才会被编码。 编码为 4-6 个字节。 如果要传输的文本包含大量英文字符,UTF-8编码可以节省空间:

字符 ASCIIUnicodeUTF-8

A

01000001

1538729559660001

01000001

中间

X

1538729559661101

153872955966153872955966

从上表还可以发现,UTF-8编码还有一个额外的好处,就是ASCII编码其实可以看作是UTF-8编码的一部分,所以大量只支持ASCII编码的遗留软件可以以 UTF-8 代码编码以继续工作。

弄清楚ASCII、Unicode和UTF-8的关系后,我们可以总结出目前计算机系统通用的字符编码工作方式:

在计算机内存中,统一使用Unicode编码,需要保存到硬盘或需要传输时,转换为UTF-8编码。

用记事本编辑时,将从文件中读取的UTF-8字符转换成Unicode字符存入内存。 编辑好后,将Unicode转为UTF-8,保存时保存到文件中:

rw-file-utf-8

python 编码成unicode_python求unicode编码_url编码和unicode编码

浏览网页时,服务器会将动态生成的Unicode内容转换为UTF-8,然后传输给浏览器:

web-utf-8

所以你在很多网页的源代码上看到类似的信息,说明该网页是用UTF-8编码的。

蟒蛇字符串

解决了麻烦的字符编码问题,我们再研究一下Python的字符串。

在最新的 Python 3 版本中,字符串采用 Unicode 编码,即 Python 字符串支持多种语言,例如:

>>> print('包含中文的str')
包含中文的str

对于单个字符的编码,Python提供了ord()函数获取字符的整数表示,chr()函数将编码转换为对应的字符:

>>> ord('A')
65
>>> ord('中')
20013
>>> chr(66)
'B'
>>> chr(25991)
'文'

如果知道字符的整数编码,也可以将 str 写成十六进制:

>>> '\u4e2d\u6587'
'中文'

这两个符号是完全等价的。

由于Python的字符串类型是str,在内存中是用Unicode表示的,一个字符对应几个字节。 如果要在网络上传输或保存到磁盘,则需要将str以字节为单位改为bytes。

Python 对 bytes 类型的数据使用单引号或双引号前缀 b :

x = b'ABC'

注意区分'ABC'和b'ABC',前者是str,虽然后者显示的内容和前者一样,但是bytes的每个字符只占一个字节。

可以通过encode()方法将Unicode表示的str编码成指定的字节,例如:

url编码和unicode编码_python求unicode编码_python 编码成unicode

>>> 'ABC'.encode('ascii')
b'ABC'
>>> '中文'.encode('utf-8')
b'\xe4\xb8\xad\xe6\x96\x87'
>>> '中文'.encode('ascii')
Traceback (most recent call last):
  File "", line 1, in 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

纯英文的str可以用ASCII编码成bytes,内容是一样的,包含中文的str可以用UTF-8编码成bytes。 含有中文的str不能用ASCII编码,因为中文编码的范围超出了ASCII编码的范围,Python会报错。

以字节为单位,不能显示为ASCII字符的字节用\x##显示。

反之,如果我们从网络或者磁盘中读取一个字节流,那么读取的数据就是字节。 要将 bytes 转换为 str,需要使用 decode() 方法:

>>> b'ABC'.decode('ascii')
'ABC'
>>> b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
'中文'

如果bytes中包含无法解码的字节,decode()方法会报错:

>>> b'\xe4\xb8\xad\xff'.decode('utf-8')
Traceback (most recent call last):
  ...
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 3: invalid start byte

如果 bytes 中只有少量无效字节,可以通过 errors='ignore' 来忽略错误的字节:

>>> b'\xe4\xb8\xad\xff'.decode('utf-8', errors='ignore')
'中'

要计算 str 包含多少个字符,可以使用 len() 函数:

>>> len('ABC')
3

python求unicode编码_python 编码成unicode_url编码和unicode编码

>>> len('中文') 2

len() 函数计算 str 中的字符数。 如果换成bytes,len()函数计算字节数:

>>> len(b'ABC')
3
>>> len(b'\xe4\xb8\xad\xe6\x96\x87')
6
>>> len('中文'.encode('utf-8'))
6

可以看出,经过UTF-8编码后,一个汉字通常占用3个字节,而一个英文字符只占用1个字节。

在操作字符串的时候,我们经常会遇到str和bytes之间的转换。 为了避免出现乱码,应该始终使用UTF-8编码来转换str和bytes。

由于Python源码也是一个文本文件,当你的源码包含中文时,你需要在保存源码时指定UTF-8编码。 Python解释器在读取源代码时,为了使其以UTF-8编码读取,我们通常会在文件开头写上这两行:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

第一行注释是告诉Linux/OS X系统这是一个Python可执行程序,Windows系统会忽略这条注释;

第二行注释是告诉Python解释器按照UTF-8编码读取源码,​​否则你在源码中写的中文输出可能出现乱码。

确认 UTF-8 编码并不意味着您的 .py 文件是 UTF-8 编码的,您必须并确保文本编辑器使用没有 BOM 编码的 UTF-8:

set-encoding-in-notepad++

如果.py文件本身使用UTF-8编码,并且还声明了#-*- coding:utf-8 -*-,打开命令提示符测试可以正常显示中文:

py-chinese-test-in-cmd

格式

最后一个常见问题是如何输出格式化字符串。 我们经常输出类似'Dear xxx hello! 你xx月的话费是xx,你的余额是xx'这样的字符串,xxx的内容是根据变量变化的,所以你需要一个简单的方法来格式化字符串。

py-str-format

在Python中,采用的格式化方式与C语言一致,用%实现,例如:

>>> 'Hello, %s' % 'world'
'Hello, world'
>>> 'Hi, %s, you have $%d.' % ('Michael', 1000000)

url编码和unicode编码_python 编码成unicode_python求unicode编码

'Hi, Michael, you have $1000000.'

正如您可能猜到的那样,% 运算符用于格式化字符串。 字符串里面,%s表示用字符串替换,%d表示用整数替换。 有几个 %? 占位符,后面跟着几个变量或值,顺序要对应。 如果只有一个%?,括号可以省略。

常见的占位符是:

占位符替换内容

%d

整数

%F

浮点数

%s

细绳

%X

十六进制整数

其中格式化整数和浮点数还可以指定是否补0以及整数和小数的位数:

# -*- coding: utf-8 -*-
----
print('%2d-d' % (3, 1))
print('%.2f' % 3.1415926)

如果您不确定要使用什么,%s 将始终有效并将任何数据类型转换为字符串:

>>> 'Age: %s. Gender: %s' % (25, True)
'Age: 25. Gender: True'

有时候,字符串中的%是普通字符怎么办? 这时候就需要转义了,用%%代表一个%:

>>> 'growth rate: %d %%' % 7
'growth rate: 7 %'

格式()

另一种格式化字符串的方法是使用字符串的 format() 方法,该方法会将字符串中的占位符 {0}, {1}... 替换为传入的参数,但这种写法比%:

>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)

url编码和unicode编码_python 编码成unicode_python求unicode编码

'Hello, 小明, 成绩提升了 17.1%'

f弦

最后一种格式化字符串的方法是使用以f开头的字符串,称为f-string,它与普通字符串的不同之处在于,如果字符串中包含{xxx},则会被替换为对应的变量:

>>> r = 2.5
>>> s = 3.14 * r ** 2
>>> print(f'The area of a circle with radius {r} is {s:.2f}')
The area of a circle with radius 2.5 is 19.62

上面代码中,{r}替换为变量r的值,{s:.2f}替换为变量s的值,并且:后面的.2f指定了格式化参数(即两位小数地方),因此python 编码成unicode,{s :.2f} 是 19.62。

实践

小明的分数从去年的72分提高到今年的85分。 请计算小明分数提高的百分点,用字符串格式化显示'xx.x%',只保留小数点后一位:

# -*- coding: utf-8 -*-
s1 = 72
s2 = 85
----
r = ???
print('???' % r)

概括

Python 3 中的字符串使用 Unicode 并直接支持多种语言。

str和bytes相互转换时,需要指定编码。 最常用的编码是UTF-8。 当然Python也支持其他编码方式,比如将Unicode编码成GB2312:

>>> '中文'.encode('gb2312')
b'\xd6\xd0\xce\xc4'

但这种方法是自找麻烦。 如果没有特殊的业务需求,请记住只使用 UTF-8 编码。

格式化字符串时,可以使用Python的交互式环境进行测试,方便快捷。

参考源码

the_string.py