• Python2和3字符编码的区别


    Python2和3字符编码的区别

    **一.字符编码应用之Pyhton **

    1.1执行Python程序的三个阶段

    test.py文件内容以gbk格式保存的,内容为:

    047-Python2与3字符编码的区别-代码编写.png?x-oss-process=style/watermark

    • 阶段一:启动Python解释器
    • 阶段二:Python解释器此时就是一个文本编辑器,负责打开文件test.py,即从硬盘中读取test.py的内容到内存中

    此时,Python解释器会读取test.py的第一行内容,#coding:utf-8#-*-coding:utf-8-*-,以此决定以什么编码格式将代码读入内存,这一行就是设定Python解释器这个软件使用的编码格式。

    可以用sys.getdefaultencoding()查看,如果不在Python文件指定头信息#-*-coding:utf-8-*-,那就使用Python默认的编码格式。

    import sys
    
    sys.getdefaultencoding()
    'utf-8'
    

    Python2中默认使用ascii,Python3中默认使用utf-8。

    047-Python2与3字符编码的区别-语法报错.png?x-oss-process=style/watermark

    改正:在test.py指定文件头,字符编码一定要为gbk。即更正为

    #coding:gbk
    你好啊
    

    047-Python2与3字符编码的区别-修正.png?x-oss-process=style/watermark

    • 阶段三:读取已经加载到内存的代码(Unicode编码格式),然后执行,执行过程中可能会开辟新的内存空间,比如name="nick"

    内存的编码使用Unicode,不代表内存中全都是Unicode,因为在程序执行之前,内存中确实都是Unicode,比如从文件中读取了一行name="nick",其中的name、等号、引号的地位都一样,都是普通字符而已,都是以Unicode的格式存放于内存中的。

    但是程序在执行过程中,会申请内存(与程序代码所存在的内存是俩个空间)用来存放Python的数据类型的值,而Python的字符串类型又涉及到了字符的概念。

    比如name="nick",会被Python解释器识别为字符串,会申请内存空间来存放字符串类型的值,至于该字符串类型的值被识别成何种编码存放,这就与Python解释器的有关了,而Python2与Python3的字符串类型又有所不同。

    二、Python2与Python3字符串类型的区别

    2.1.1 str类型

    当Python解释器执行到产生字符串的代码时(例如x='上'),会申请新的内存地址,然后将'上'编码成文件开头指定的编码格式

    因为直接print()会自动转换编码,我们使用encode()方法查看'上'的字符编码。

    # 三、Python2中代码
    
    # 四、coding:gbk
    
    x = '上'
    y = '下'
    print([x, y])  # ['xc9xcf', 'xcfxc2']
    # 五、x代表16进制,此处是c9cf总共4位16进制数,一个16进制四4个比特位,4个16进制数则是16个比特位,即2个Bytes,这就证明了按照gbk编码中文用2Bytes
    
    print(type(x),type(y))  # (<type 'str'>, <type 'str'>)
    

    理解字符编码的关键!!!

    内存中的数据通常用16进制表示,2位16进制数据代表一个字节,如xc9,代表两位16进制,一个字节

    gbk存中文需要2个bytes,而存英文则需要1个bytes,它是如何做到的???!!!

    gbk会在每个bytes,即8位bit的第一个位作为标志位,标志位为1则表示是中文字符,如果标志位为0则表示为英文字符。

    x='你a好'`
    转成gbk格式二进制位:`8bit+8bit+8bit+8bit+8bit=(1+7bit)+(1+7bit)+(0+7bit)+(1+7bit)+(1+7bit)
    

    这样计算机按照从左往右的顺序读:

    1. 连续读到前两个括号内的首位标志位均为1,则构成一个中午字符:你
    2. 读到第三个括号的首位标志为0,则该8bit代表一个英文字符:a
    3. 连续读到后两个括号内的首位标志位均为1,则构成一个中午字符:好

    也就是说,每个Bytes留给我们用来存真正值的有效位数只有7位,而在Unicode表中存放的只是这有效的7位,至于首位的标志位与具体的编码有关,即在Unicode中表示gbk的方式为:(7bit)+(7bit)+(7bit)+(7bit)+(7bit)

    047-Python2与3字符编码的区别-gbk上.png?x-oss-process=style/watermark

    按照上图翻译的结果,我们可以去Unicode关于汉字的对应关系中去查:链接:https://pan.baidu.com/s/1dEV3RYp

    可以看到“上”对应的gbk(G0代表的是gbk)编码就为494F,即我们得出的结果,而上对应的Unicode编码为4E0A,我们可以将gbk-->decode-->Unicode。

    047-Python2与3字符编码的区别-Unicode上.png?x-oss-process=style/watermark

    # 六、Python2中代码
    
    # 七、coding:gbk
    
    x = '上'.decode('gbk')
    y = '下'.decode('gbk')
    print([x, y])  # [u'u4e0a', u'u4e0b']
    

    7.0.2 Unicode类型

    当Python解释器执行到产生字符串的代码时(例如s=u'林'),会申请新的内存地址,然后将'林'以Unicode的格式存放到新的内存空间中,所以s只能encode,不能decode。

    # 八、Python2中代码
    
    # 九、coding:gbk
    
    x = u'上'  # 等同于 x='上'.decode('gbk')
    y = u'下'  # 等同于 y='下'.decode('gbk')
    print([x, y])  # [u'u4e0a', u'u4e0b']
    print(type(x),type(y))  # (<type 'Unicode'>, <type 'Unicode'>)
    

    对于print需要特别说明的是:当程序执行时,比如x='上' # gbk下,字符串存放为xc9xcf

    print(x)这一步是将x指向的那块新的内存空间(非代码所在的内存空间)中的内存,打印到终端,按理说应该是存的什么就打印什么,但打印xc9xcf,对一些不熟知Python编码的程序员,立马就懵逼了,所以龟叔自作主张,在print(x)时,使用终端的编码格式,将内存中的xc9xcf转成字符显示,此时就需要终端编码必须为gbk,否则无法正常显示原内容:上。

    047-Python2与3字符编码的区别上1.png?x-oss-process=style/watermark

    047-Python2与3字符编码的区别-上2.png?x-oss-process=style/watermark

    对于Unicode格式的数据来说,无论怎么打印,都不会乱码

    047-Python2与3字符编码的区别-上3.png?x-oss-process=style/watermark

    047-Python2与3字符编码的区别-上4.png?x-oss-process=style/watermark

    Unicode这么好,不会乱码,那Python2为何还那么别扭,搞一个str出来呢?Python诞生之时,Unicode并未像今天这样普及,很明显,好的东西你能看得见,龟叔早就看见了,龟叔在Python3中将str直接存成Unicode,我们定义一个str,无需是否加u前缀,就是一个Unicode,屌不屌?

    9.1 Python3

    # coding:gbk
    x = '上'  # 当程序执行时,无需加u,'上'也会被以Unicode形式保存新的内存空间中,
    
    print(f"type(x): {type(x)}")  # <class 'str'>
    
    # x可以直接encode成任意编码格式
    print(f"x.encode('gbk'): {x.encode('gbk')}")  # b'xc9xcf'
    print(f"type(x.encode('gbk')): {type(x.encode('gbk'))}")  # <class 'bytes'>
    type(x): <class 'str'>
    x.encode('gbk'): b'xc9xcf'
    type(x.encode('gbk')): <class 'bytes'>
    

    很重要的一点是:看到Python3中x.encode('gbk') 的结果xc9xcf正是Python2中的str类型的值,而在Python3是bytes类型,在Python2中则是str类型。

  • 相关阅读:
    解决行内块元素(inline-block)之间的空格或空白问题
    gzip压缩文件&webPack配置Compression-webpack-plugin
    IOS微信禁用分享跳转页面返回BUG修复
    开发自己的composer包
    深入理解Java中的迭代器
    理解JDK1.5的自动装箱拆箱
    [design-patterns]设计模式之一策略模式
    [java]final关键字的几种用法
    [java]static关键字的四种用法
    [java]我的数据在哪里?——数据的内存模型
  • 原文地址:https://www.cnblogs.com/kangwy/p/11317570.html
Copyright © 2020-2023  润新知