• str和unicode类


    在py2中,分为两类,str和unicode

    而在py3中,分为两类,byte和str

     py2中的str等同于py3中的byte

    首先明确一点,我们编辑好一段文本,python并不知道我们的文本是以什么格式编码的。如果是纯英文字符还好说,如果这段代码中有汉字,则会报错了。

    所以我们要显式的告诉python此文本的编码格式。

    为了说明问题,首先将以下测试代码以utf-8格式编辑保存

     1 # -*- coding:utf-8 -*-  #告知python我这个文件里的文本是用utf-8编码的,如果不加,而文本中又包含汉字,没运行前就会报错
     2 import time
     3 
     4 a = ''
     5 print a#乱码,a是utf-8格式,而windows控制台使用gbk进行解码
     6 b = unicode(a,'utf-8').encode('gbk')#将严先解码为unicode格式,在编码为gbk格式
     7 print b#正确显示严
     8 c = a.decode('utf-8')#等效于c = unicode('严','utf-8'),亦等效于c = u'严' c是unicode格式的
     9 print type(a),type(b),type(c)#a,b都是str类,c是unicode类
    10 print c
    11 time.sleep(4)

     但是还有一个疑问,既然windows控制台使用gbk解码,为什么utf8的a是乱码,而unicode的b就不会是乱码呢?

    因为Python在向控制台输出unicode对象的时候会自动根据输出环境的编码进行转换,这样就能正确解码了。但如果输出的不是unicode对象而是普通字符串,则控制台并不会参考我们声明的编码格式进行str到unicode的转换,而是直接会按照终端编码去解码a(cmd编码为gbk,linux系统默认编码为utf8),当然会出错

    事实上最简单的str转unicode的方式是在字符串前加u,如u'严',python会根据第一行标明的coding,来认定‘严’的格式,然后转换为unicode格式

    2.encode与decode

    首先明确一点,python认定unicode为指定编码。从其他编码转为unicode叫做解码,从unicode转为str叫做编码,

    而任何两种字符编码之间如果想完成转化,必须要通过unicode这个桥梁,先把它抓化成unicode对象,在转为另一个编码

    encode是将unicode类对象编码成其他格式,所以正规调用为unicode.encode()

    decode是将str类对象解码成unicode类对象,所以正规调用是str.decode()

    但是Python允许str.encode(),也允许unicode.decode()。

    这里涉及隐式类型转化的问题

    str.encode()实际上就等价于str.decode(sys.getdefaultencoding()).encode().而sys.defaultencoding如果不改的话默认是ascii,所以这里的str不能是中文字符。

    unicode.decode()会先将unicode转化成str,然后再执行decode()

    函数decode()有默认参数,默认参数为sys.getdefaultencoding()。

    3关于sys.getdefaultencoding()

    这是sys模块的内置方法,该方法返回python的默认编码。

    以下为转载:http://liguangming.com/how-to-use-utf-8-with-python

    python 中获得系统默认编码为:

    import sys
    print sys.getdefaultencoding()
    而修改系统默认编码应写为:
    import sys
    reload(sys)
    sys.setdefaultencoding('UTF-8')
    为什么需要一个看似多余的reload(sys)呢? 因为python初始化后会删除 sys.setdefaultencoding 这个方法,我们需要重新载入

    先看下python的模块加载过程:

    # python -v
    # installing zipimport hook
    import zipimport # builtin
    # installed zipimport hook
    # /usr/local/lib/python2.6/site.pyc matches /usr/local/lib/python2.6/site.py
    import site # precompiled from /usr/local/lib/python2.6/site.pyc
    ....
    Python运行的时候首先加载了site.py,在site.py文件里有这么一段代码:
    if hasattr(sys, "setdefaultencoding"):
        del sys.setdefaultencoding
    

    在sys加载后,setdefaultencoding方法被删除了,所以我们要通过重新导入sys来设置系统编码.

    4

    判断是否为unicode/str的方法

    [python] view plain copy
     
    1. >>> isinstance(u‘中文‘, unicode) True   
    2. >>> isinstance(‘中文‘, unicode) False    
    3. >>> isinstance(‘中文‘, str) True   
    4. >>> isinstance(u‘中文‘, str) False 

    5py3中的bytes和unicode

    如果说在Python2中,第一行的声明可以和文件实际采用的编码格式不相一致,只是这样就不能用u'汉字'的形式将str转换为unicode了,但是仍然可以用unicode方法或decode方法转换。比如我在python文件中声明coding=utf-8,而我编辑这个文件的时候实际采用的编码是gbk。所以在python2中第一行声明conding的作用好像也仅仅局限于可以用u'汉字'的形式将str转换为unicode了。声明错了也无大碍。当然最好要保持一致。

    但是在python3中,第一行声明的coding就作用大了,必须声明正确。直接用代码加以说明吧,代码来自大神crifanhttps://www.crifan.com/summary_python_string_encoding_decoding_difference_and_comparation_python_2_x_str_unicode_vs_python_3_x_bytes_str/

    python_3.x_str_to_bytes.py

     1 #!/usr/bin/python
     2 # -*- coding: utf-8 -*-
     3 """
     4 -------------------------------------------------------------------------------
     5 Function:
     6 【整理】Python中字符编码的总结和对比:Python 2.x的str和unicode vs Python 3.x的bytes和str
     7 http://www.crifan.com/summary_python_string_encoding_decoding_difference_and_comparation_python_2_x_str_unicode_vs_python_3_x_bytes_str
     8  
     9 Author:     Crifan
    10 Verison:    2012-11-29
    11 -------------------------------------------------------------------------------
    12 """
    13  
    14 def python3xStrToBytes():
    15     """Demo Python 3.x (unicode) str to bytes
    16     """
    17      
    18     zhcnUnicode = "1.此处的,Python 3.x中,默认字符串的写法,就已经是unicode类型的字符串了。2.当然,还是有一点前提的,那就是,你在(1)此处python文件所指定的编码类型(2)要和你当前python文件实际所采用的编码类型,要匹配和一致,即此处,两者均是UTF-8,所以,Python解析器,才能正确的将我们此处所输入的UTF-8的中文字符,正确地解码为对应的Unicode字符串的;3.接下来将要演示的是,打印对于的此处字符的类型;然后再直接输出显示到windows的GBK编码的cmd中";
    19     print("type(zhcnUnicode)=",type(zhcnUnicode)); #type(zhcnUnicode)= <class 'str'>
    20     zhcnGbkBytes = zhcnUnicode.encode("GBK");
    21     print("You should see these zh-CN bytes in windows cmd normally, which begin with b preffix: zhcnGbkBytes=%s"%(zhcnGbkBytes)); #You should see these zh-CN bytes in windows cmd normally, which begin with b preffix: zhcnGbkBytes=b'1.xb4xcbxb4xa6xb5 ...... xc2xebxb5xc4cmdxd6xd0'
    22      
    23 ###############################################################################
    24 if __name__=="__main__":
    25     python3xStrToBytes();

    python_3.x_bytes_to_str.py

     1 #!/usr/bin/python
     2 # -*- coding: utf-8 -*-
     3 """
     4 -------------------------------------------------------------------------------
     5 Function:
     6 【整理】Python中字符编码的总结和对比:Python 2.x的str和unicode vs Python 3.x的bytes和str
     7 http://www.crifan.com/summary_python_string_encoding_decoding_difference_and_comparation_python_2_x_str_unicode_vs_python_3_x_bytes_str
     8  
     9 Author:     Crifan
    10 Verison:    2012-11-29
    11 -------------------------------------------------------------------------------
    12 """
    13  
    14 def python3xBytesToStr():
    15     """Demo Python 3.x bytes to (unicode) str
    16     """
    17      
    18     #此处的bytes,只能接受ASCII字符
    19     #想要输入非ASCII的字符,则只能通过xYY的十六进制方式输入,其中YY为对应的16进制的值
    20     #此处,我是已经在别处,通过把对应的中文:
    21     #"1.Python 3.x中,给字符串前面添加字母b,表示是bytes的字符串;2.此处之所以可以实现,接下来的,Python解析器,可以正确的将bytes解码为Unicode的str,那是因为(1)此处python文件所指定的编码类型(2)要和你当前python文件实际所采用的编码类型,是一致的,都是UTF-8;3.接下来将要演示的是,将此bytes字符串,解码为Unicode的str,然后在此处的终端,windows的默认编码为GBK的cmd中显示出来;";
    22     #解析为UTF-8的bytes了,所以下面你看到的是,解析后的,一堆bytes
    23      
    24     zhcnBytes = b"1.xe6xadxa4xe5xa4x84xe7x9ax84xefxbcx8cPython 3.xxe4xb8xadxefxbcx8cxe9xbbx98xe8xaexa4xe5xadx97xe7xacxa6xe4xb8xb2xe7x9ax84xe5x86x99xe6xb3x95xefxbcx8cxe5xb0xb1xe5xb7xb2xe7xbbx8fxe6x98xafunicodexe7xb1xbbxe5x9ex8bxe7x9ax84xe5xadx97xe7xacxa6xe4xb8xb2xe4xbax86xe3x80x822.xe5xbdx93xe7x84xb6xefxbcx8cxe8xbfx98xe6x98xafxe6x9cx89xe4xb8x80xe7x82xb9xe5x89x8dxe6x8fx90xe7x9ax84xefxbcx8cxe9x82xa3xe5xb0xb1xe6x98xafxefxbcx8cxe4xbdxa0xe5x9cxa8(1)xe6xadxa4xe5xa4x84pythonxe6x96x87xe4xbbxb6xe6x89x80xe6x8cx87xe5xaex9axe7x9ax84xe7xbcx96xe7xa0x81xe7xb1xbbxe5x9ex8b(2)xe8xa6x81xe5x92x8cxe4xbdxa0xe5xbdx93xe5x89x8dpythonxe6x96x87xe4xbbxb6xe5xaex9exe9x99x85xe6x89x80xe9x87x87xe7x94xa8xe7x9ax84xe7xbcx96xe7xa0x81xe7xb1xbbxe5x9ex8bxefxbcx8cxe8xa6x81xe5x8cxb9xe9x85x8dxe5x92x8cxe4xb8x80xe8x87xb4xefxbcx8cxe5x8dxb3xe6xadxa4xe5xa4x84xefxbcx8cxe4xb8xa4xe8x80x85xe5x9dx87xe6x98xafUTF-8xefxbcx8cxe6x89x80xe4xbbxa5xefxbcx8cPythonxe8xa7xa3xe6x9ex90xe5x99xa8xefxbcx8cxe6x89x8dxe8x83xbdxe6xadxa3xe7xa1xaexe7x9ax84xe5xb0x86xe6x88x91xe4xbbxacxe6xadxa4xe5xa4x84xe6x89x80xe8xbex93xe5x85xa5xe7x9ax84UTF-8xe7x9ax84xe4xb8xadxe6x96x87xe5xadx97xe7xacxa6xefxbcx8cxe6xadxa3xe7xa1xaexe5x9cxb0xe8xa7xa3xe7xa0x81xe4xb8xbaxe5xafxb9xe5xbax94xe7x9ax84Unicodexe5xadx97xe7xacxa6xe4xb8xb2xe7x9ax84xefxbcx9b3.xe6x8exa5xe4xb8x8bxe6x9dxa5xe5xb0x86xe8xa6x81xe6xbcx94xe7xa4xbaxe7x9ax84xe6x98xafxefxbcx8cxe6x89x93xe5x8dxb0xe5xafxb9xe4xbax8exe7x9ax84xe6xadxa4xe5xa4x84xe5xadx97xe7xacxa6xe7x9ax84xe7xb1xbbxe5x9ex8bxefxbcx9bxe7x84xb6xe5x90x8exe5x86x8dxe7x9bxb4xe6x8exa5xe8xbex93xe5x87xbaxe6x98xbexe7xa4xbaxe5x88xb0windowsxe7x9ax84GBKxe7xbcx96xe7xa0x81xe7x9ax84cmdxe4xb8xad";
    25     print("type(zhcnBytes)=",type(zhcnBytes)); #type(zhcnBytes)= <class 'bytes'>
    26     zhcnUnicodeStr = zhcnBytes.decode("UTF-8");
    27     print("You should see these zh-CN unicode str in windows cmd normally: zhcnUnicodeStr=%s"%(zhcnUnicodeStr)); #You should see these zh-CN unicode str in windows cmd normally: zhcnUnicodeStr=1.此处的,Python 3.x中 ...... 然后再直接输出显示到windows的GBK编码的cmd中
    28      
    29 ###############################################################################
    30 if __name__=="__main__":
    31     python3xBytesToStr();

    【总结】

    如果你正确声明(指定)了文件编码的话,那么python 3.x中对于你所写的字符串,默认会自动解析并存储为Unicode的,(这里的存储,指的是代码从文件载入到内存中)所有后期的各种处理,包括在cmd中的输出,都会很好的自动转换为对应的编码并输出显示的,比如输出到cmd中,会自动转换为cmd的GBK编码,得以正确显示的

    #-*-coding:utf8;-*-
    #py2
    a=''
    b='xe6x96xb0'
    print a==b#True
    #a在百分之99的情况下都与b相同,只有一种情况下不同
    c=u'新'
    d=u'xe6x96xb0'#报错

    #-*-coding:utf8;-*-
    #py2
    a=u'u4e2d'
    b=u'中'
    print a==b#true
    #-*-coding:utf8;-*-
    #py3
    
    a='u4e2d'
    b='中'
    print (a==b)#true
  • 相关阅读:
    Python基础学习四 文件操作(二)
    Python基础学习三 文件操作(一)
    Python基础学习三 字符串
    Python基础学习三 字典、元组
    Python基础学习三 list-增删改查、切片、循环、排序
    python基础4文件操作
    Python基础3切片,字符串的方法,for 循环
    python2和Python3的区别(长期更新)
    Python基础1
    python 中的enumerate()函数的用法
  • 原文地址:https://www.cnblogs.com/saolv/p/8158159.html
Copyright © 2020-2023  润新知