❶ python 什麼是magic string
無論是python還是其它的編程語言,都有magic string這類東西存在。它並不是phtyon專有的東西。類似的還有magic number這樣的。
前兩年有關linux一個版本的更新就有個關於魔法數字的小插曲:
linux一個版本更新出來後,對某個類型的顯卡的驅動支持出現了問題,然後相關代碼被修復,其中在代碼中就直接對一個地址加了一個偏移量,類似python中addr_offset += 123這樣的操作,這里,這個123就是一個魔法數:它為什麼是123?為什麼不可以是124或者別的什麼值?沒有說明,沒有理由,它就這么神奇的出現,然後問題就神奇的被解決了。
為此,linux項目負責人員很惱火,在項目中都說了臟話。
無論是magic string還是magic number,統稱為magic value,即,魔法值。
它們在代碼中突然出現,直接使用,沒有說明,無從追溯。
這對代碼的可讀性,可維護性都帶來了負面效應。
拿個簡單的例子來說,在python中,我們有時會使用zipfile來處理壓縮文件,比如這樣:
z_file.writestr(z_name,data,zipfile.ZIP_DEFLATED)
但如果寫成:
z_file.writestr(z_name,data,8)
那麼,這個8就是一個魔法值:它是什麼?它哪裡來的?為什麼是8而不是9?除非你去讀zlip的文檔或源代碼,否則不知道這個8是什麼。而使用`zipfile.ZIP_DEFLATED`的話,即使你不了解zlip,看到這個常量名,也知道它是壓縮(deflated)的zip選擇了。
魔法值讓我們需要了解相關很多內容時才能讀懂一句代碼,並且修改它的功能或修正它的bug需要同樣多的精力。
再拿一個例子來說:
defgetfileencode(file):
"""測試得到文本類型文件可能使用的編碼格式
它不一定就是正確的
>>>getfileencode('errorlog.txt')
'utf_8_sig'
>>>getfileencode('星.txt')
'gb18030'
>>>getfileencode(r'D:/Python/baseweb\app.py')
'utf_8'
"""
codes=['utf_8','utf_16','gb18030','big5']
withopen(file,'rb')asf:
b=f.read()
forcodeincodes:
try:
b.decode(code)
ifcode=='utf_8'andb.startswith(b'xefxbbxbf'):
code='utf_8_sig'
break
except(Exception,):
continue
returncode
第17行中的b'xefxbbxbf'就是一個魔法值,為什麼是這個值?你只有了解到windows(MS)自作主張的在utf-8編碼的文本文件最開始加了這么一段作為這種編碼的標識時,才能理解為什麼這么寫。如果我們將它命名為一個常量:
UTF8_BOM=b'xefxbbxbf'
然後在代碼中的if這樣寫:
ifcode=='utf_8'andb.startswith(UTF8_BOM)
你無需了解關於微軟在utf-8文件前加了什麼,就能知道這個判斷的意思:如果它是utf-8編碼,並且以BOM開始……
這是避免代碼中出現魔法值的最常見的辦法。
❷ ASCII、Unicode、UTF-8、UTF-8(without BOM)傻傻分不清
前言
Github上下載了一份代碼打算學習,源工程是在linux上開發的,我在Windows上編譯通過不了,很多莫名奇妙的錯誤,最後發現源代碼文件是UTF-8(without BOM)編碼的,Notepad++修改編碼格式為UTF-8編譯通過。
ASCII
畢竟在電子系混過四年,這個詞不陌生,用一個位元組的低7位來表示128個英文字元(0xxxxxxx),可是地球上的文字又不是只有英文,光漢字就好幾萬個,所以每個國家和地區又做了一套符合自身情況的編碼規范,比如簡體中文編碼標准GB2312,使用兩個位元組來表示一個漢字,可以表示65536個中文字元。但是如果每個國家都這么搞那不就亂套了嘛,於是Unicode就應運而生了。
Unicode
Unicode是個符號集,與ASCII類似,只不過容量要大得多,可以理解成一張表,為世界上的每一個字元指定了一個惟一的二進制代碼,但是它並沒有規定這個二進制代碼如何存儲,於是乎UTF-8、UTF-8(without bom)、UTF-16、UTF-32應運而生。
UTF-8
UTF-8是Unicode的實現方式之一,最大特點就是根據符號自動變化位元組長度,即可變長編碼,編碼方式如下圖所示:
UTF-8(without BOM)
BOM(Byte Order Mark)位元組順序標記,即可以用來標記是大端還是小端。在Unicode裡面定義了一個叫做」ZERO WITH NO-BREAK SPACE「的不可見字元,對應的Unicode編碼是FEFF,有BOM的文件即文件開頭有」ZERO WITH NO-BREAK SPACE「不可見字元,反之則沒有。若是大端編碼,則文件開頭是FEFF,小端則是FFFE。BOM是為了配合UTF-16和UTF-32使用,因為它們編碼編碼單元包含多個位元組,涉及位元組序的問題。
UTF-8以單位元組為編碼單元,不存在位元組序的問題,但是可以使用BOM來表明所使用的編碼方式,字元」ZERO WITH NO-BREAK SPACE「在UTF-8中的編碼是EF BB BF,所以當解碼文件時發現開頭的單個位元組是EF BB BF即說明是UTF-8編碼,Windows就是使用BOM來標記文本的編碼方式的。
怎樣區分UTF-8、UTF-16和UTF-32
打開文本時根據BOM來區分當前文件的編碼類型