展开全部

无论是python还是其它的编程语言,都有magic string这类东西存在。它并不是phtyon专有32313133353236313431303231363533e4b893e5b19e31333366303138的东西。类似的还有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需要同样多的精力。

再拿一个例子来说:def getfileencode(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']
with open(file, 'rb') as f:
b = f.read()
for code in codes:

try:

b.decode(code)
if code == 'utf_8' and b.startswith(b'\xef\xbb\xbf'):
code = 'utf_8_sig'
break
except (Exception,):
continue
return code

第17行中的b'\xef\xbb\xbf'就是一个魔法值,为什么是这个值?你只有了解到windows(MS)自作主张的在utf-8编码的文本文件最开始加了这么一段作为这种编码的标识时,才能理解为什么这么写。如果我们将它命名为一个常量:UTF8_BOM = b'\xef\xbb\xbf'

然后在代码中的if这样写:if code == 'utf_8' and b.startswith(UTF8_BOM)

你无需了解关于微软在utf-8文件前加了什么,就能知道这个判断的意思:如果它是utf-8编码,并且以BOM开始……

这是避免代码中出现魔法值的最常见的办法。