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.\xb4\xcb\xb4\xa6\xb5 ...... \xc2\xeb\xb5\xc4cmd\xd6\xd0'
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.\xe6\xad\xa4\xe5\xa4\x84\xe7\x9a\x84\xef\xbc\x8cPython 3.x\xe4\xb8\xad\xef\xbc\x8c\xe9\xbb\x98\xe8\xae\xa4\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2\xe7\x9a\x84\xe5\x86\x99\xe6\xb3\x95\xef\xbc\x8c\xe5\xb0\xb1\xe5\xb7\xb2\xe7\xbb\x8f\xe6\x98\xafunicode\xe7\xb1\xbb\xe5\x9e\x8b\xe7\x9a\x84\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2\xe4\xba\x86\xe3\x80\x822.\xe5\xbd\x93\xe7\x84\xb6\xef\xbc\x8c\xe8\xbf\x98\xe6\x98\xaf\xe6\x9c\x89\xe4\xb8\x80\xe7\x82\xb9\xe5\x89\x8d\xe6\x8f\x90\xe7\x9a\x84\xef\xbc\x8c\xe9\x82\xa3\xe5\xb0\xb1\xe6\x98\xaf\xef\xbc\x8c\xe4\xbd\xa0\xe5\x9c\xa8(1)\xe6\xad\xa4\xe5\xa4\x84python\xe6\x96\x87\xe4\xbb\xb6\xe6\x89\x80\xe6\x8c\x87\xe5\xae\x9a\xe7\x9a\x84\xe7\xbc\x96\xe7\xa0\x81\xe7\xb1\xbb\xe5\x9e\x8b(2)\xe8\xa6\x81\xe5\x92\x8c\xe4\xbd\xa0\xe5\xbd\x93\xe5\x89\x8dpython\xe6\x96\x87\xe4\xbb\xb6\xe5\xae\x9e\xe9\x99\x85\xe6\x89\x80\xe9\x87\x87\xe7\x94\xa8\xe7\x9a\x84\xe7\xbc\x96\xe7\xa0\x81\xe7\xb1\xbb\xe5\x9e\x8b\xef\xbc\x8c\xe8\xa6\x81\xe5\x8c\xb9\xe9\x85\x8d\xe5\x92\x8c\xe4\xb8\x80\xe8\x87\xb4\xef\xbc\x8c\xe5\x8d\xb3\xe6\xad\xa4\xe5\xa4\x84\xef\xbc\x8c\xe4\xb8\xa4\xe8\x80\x85\xe5\x9d\x87\xe6\x98\xafUTF-8\xef\xbc\x8c\xe6\x89\x80\xe4\xbb\xa5\xef\xbc\x8cPython\xe8\xa7\xa3\xe6\x9e\x90\xe5\x99\xa8\xef\xbc\x8c\xe6\x89\x8d\xe8\x83\xbd\xe6\xad\xa3\xe7\xa1\xae\xe7\x9a\x84\xe5\xb0\x86\xe6\x88\x91\xe4\xbb\xac\xe6\xad\xa4\xe5\xa4\x84\xe6\x89\x80\xe8\xbe\x93\xe5\x85\xa5\xe7\x9a\x84UTF-8\xe7\x9a\x84\xe4\xb8\xad\xe6\x96\x87\xe5\xad\x97\xe7\xac\xa6\xef\xbc\x8c\xe6\xad\xa3\xe7\xa1\xae\xe5\x9c\xb0\xe8\xa7\xa3\xe7\xa0\x81\xe4\xb8\xba\xe5\xaf\xb9\xe5\xba\x94\xe7\x9a\x84Unicode\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2\xe7\x9a\x84\xef\xbc\x9b3.\xe6\x8e\xa5\xe4\xb8\x8b\xe6\x9d\xa5\xe5\xb0\x86\xe8\xa6\x81\xe6\xbc\x94\xe7\xa4\xba\xe7\x9a\x84\xe6\x98\xaf\xef\xbc\x8c\xe6\x89\x93\xe5\x8d\xb0\xe5\xaf\xb9\xe4\xba\x8e\xe7\x9a\x84\xe6\xad\xa4\xe5\xa4\x84\xe5\xad\x97\xe7\xac\xa6\xe7\x9a\x84\xe7\xb1\xbb\xe5\x9e\x8b\xef\xbc\x9b\xe7\x84\xb6\xe5\x90\x8e\xe5\x86\x8d\xe7\x9b\xb4\xe6\x8e\xa5\xe8\xbe\x93\xe5\x87\xba\xe6\x98\xbe\xe7\xa4\xba\xe5\x88\xb0windows\xe7\x9a\x84GBK\xe7\xbc\x96\xe7\xa0\x81\xe7\x9a\x84cmd\xe4\xb8\xad";
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='\xe6\x96\xb0'
print a==b#True
#a在百分之99的情況下都與b相同,只有一種情況下不同
c=u'新'
d=u'\xe6\x96\xb0'#報錯

 

#-*-coding:utf8;-*-
#py2
a=u'\u4e2d'
b=u'中'
print a==b#true
#-*-coding:utf8;-*-
#py3

a='\u4e2d'
b='中'
print (a==b)#true

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM