给自己与初学者关于decode,encode的建议(啥utf-8,GBK)。

2021-01-18更新

 参考链接:https://www.bilibili.com/video/BV1Sp4y1U7Jr?p=160

最近一直空的时候看一些老男孩的教学视频,对基础的Python知识查漏补缺。

刚看到字符的解码与编码问题,记录一些我自己的学习感悟吧。

当我们在终端输出看到的,包括一些文本编辑器看到的,理论上面都是Unicode的字符串形式。

当我们打开一个文本文件的时候,必须用一直指定的编码形式来解码文件中的数据,你可以用各种不同的编码集,但正确的应该是你写入硬盘的时候的编码集。

说到底,文字还是给人看的,计算机最终的保存还是二进制的文件,在20世纪90年代,为了创造一种能包含全球文字的字符集出现了,那就是Unicode。

计算机启动后,内存中应该运行这个Unicode字符集的类似与mapping的程序,这是一个大型的中转站,因为现在的计算机必须要基本的需求,能够显式各种文字。

所以Unicode的每一个字都又对应的不同字符集的对应的编码,可以理解为Unicode的每一个字为key,不同的字符集的编码为value,而且是一对多的。

好比一个中文字"好"的Unicode编码为'\u597d',他针对不同的字符集有着不同的对应编码。

我说的是假如:GBK下面对应的是\x1122,这样的话,如果通过GBK的方式保存在电脑的话数据就是\x1122,但打开的时候通过GBK解码,会找到对应Unicode的编码,从而显式正常的数值。

按照现在的趋势来看,后续的任何文本操作都应该保存为utf8格式,因为utf8是Unicode的一种转换表达,简单理解utf8与Unicode的编码存在一一对应的关系。

但另外的字符集可能就会出现问题,中国的字符集不能编码日文,从而不能保存有日文的信息。

 

对于不能理解字符集相关知识的朋友,记住一点就够了,就是从现在开始,任何的文本文件都用utf8进行操作与保存就对了。在计算机内部Unicode的暂存是因为给另外的编码集当中转站使用。

 

 

 

 

学了不少时间了,对于字符串的编码与解码总算有了一些认识。

记录一些自己的想法。

首先,在Python3里面,我们的str类型,相当于Python2的中unicode。

>>> name = '四店'
>>> name
'\xe5\x9b\x9b\xe5\xba\x97'
>>> uname = name.decode('utf-8')
>>> print name
四店
>>> print uname
四店
>>> uname
u'\u56db\u5e97'
>>> type(uname)
<type 'unicode'>
>>> type(name)
<type 'str'>

 上面的是在python2中运行的结果,可以看到终端模式下,输入字符串对象只会出来对象的字节码数据,只有在print输出的时候,才出现对应的文字。

但在Python3中完全不一样了,py3的str就是py2的unicode

In [663]: name = u'\u56db\u5e97'                                                                                        

In [664]: name                                                                                                          
Out[664]: '四店'

In [665]: uname = name.encode('utf8')                                                                                   

In [666]: uname                                                                                                         
Out[666]: b'\xe5\x9b\x9b\xe5\xba\x97'

In [667]: print(name)                                                                                                   
四店

In [668]: print(uname)                                                                                                  
b'\xe5\x9b\x9b\xe5\xba\x97'

在这里可以看到,我们赋值给name的unicode的字符标识,但无论是终端还是print输出,name一直是四点了。

name明显是str模式,所以证明了前面说的。

 

后面流畅的Python我会记录自己的更加详细对与解码,编码的理解。

 

其实想通了感觉也就那么回事,网上好多资料,基本都是一大抄。

 

我最后稍微总结一下。unicode就是一份超级大字典,全世界所有的文字都有,所以Python终端显示用unicode蛮好

但unicode的对应表,很多人觉的传输数据的时候不好,就搞出来了utf-8,utf-16,utf-32,这个也是一份映射表。

假如在unicode里面,每个文字的名字相当与码位,utf-8,utf-16就好比编号。

比如"好"的unicode为u'\u597d',utf-8为'\xe5\xa5\xbd'

这个一对一对应的,就是说,unicode里面的每一个字符都可以找到utf-8的对应字节序(通俗讲就是编号)。

所以大家应该用utf-8。

 

再来说一些地方与国家的编码,比如中国的gbk,gbk包含了全部的中国字与字节码的映射关系,可以想象成这是一本,中国的地方字典。

In [669]: name                                                                                                          
Out[669]: '四店'

In [670]: bytes(name,encoding='gbk')                                                                                    
Out[670]: b'\xcb\xc4\xb5\xea'

 当我们在encode的时候,首先先拿gbk对照表里面的字来对比需要解码的字,比如第一个四字,找到了它的序号为\xcb\xc4,然后对编号进行输出。

所以这个很容易造成问题,你如果给一个他字符集没有的字,找了老半天才找到。

In [679]: '\u20ac'.encode('gbk')                                                                                        
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-679-90f6ff568b6b> in <module>
----> 1 '\u20ac'.encode('gbk')

UnicodeEncodeError: 'gbk' codec can't encode character '\u20ac' in position 0: illegal multibyte sequence

In [680]: '\u20ac'                                                                                                      
Out[680]: '€'

 就报错了,话说gbk的字符集还是蛮厉害了,输入了日本字,意大利的字,基本都有。

但对于utf-8只要是unicode的字符,他都能编码

In [680]: '\u20ac'                                                                                                      
Out[680]: '€'

In [681]: '\u20ac'.encode('U8')                                                                                         
Out[681]: b'\xe2\x82\xac'

 所以再次推荐大家以后都用utf-8这样的话,以后里面的decode,encode的ignore参数都可以不用了。

 

 

这里还有一份老外写的参考链接:https://pycoders-weekly-chinese.readthedocs.io/en/latest/issue5/unipain.html

还行吧,反正我没咋看懂,应该有很多py2的说明,py2基本没啥节操过。

 

前面写的我就不删除了,从流畅的Python书中指出,Python内置100多种字符编码。

我的理解就是,当给你一个字符假如是"我",Python的100多种解码器中能找到"我"的对应的字节序列是不一样的。

你通过编码的方式把unicode中的"我"转换成字节序列,可以是2字节,也可能是3字节。

可以用于计算机的存储,或者网络的传输,但机器看的懂的,人看不懂,当需要人看的时候,你又需要用同样的方式把机器的字节序列装换成人看的懂的。

这个就是解码。你用什么编码的,就必须用什么解码,其实有了utf8,另外的编码方式真的应该淘汰了。

解码以后就是unicode了,你可以把unicode想象成就是文字。

但unicode变成文字是在哪里实现,又是如何实现的,网上的资料比较少。所以我只能把unicode想象成文件了,

因为你编码的时候就是对unicode进行编码。

 

2020年12月4日补充

一段时间的学习与成长,Python网络编程书中说到Python的字符串(character)包含了Unicode字符。以前一直对这个不是很懂,很多书籍解释了,可能是翻译问题,或者我理解问题,不能很好的理解Unicode与Python中的字符串的意思。我现在的理解,就是Python的字符串,就是一堆Unicode。当你在Python的编辑器环境下,只要看到了字符串内有\u形式的字符,就会通过Unicode字符表找到对应码点(code point)的字符

这里一些记录:https://www.zhihu.com/question/26921730/answer/1610972540

posted @ 2019-12-17 20:08  就是想学习  阅读(2399)  评论(0编辑  收藏  举报