如何写出优雅的代码:从初学者到艺术家的编程规范与技巧
如何写出优雅的代码

刚开始学习编程的时候,最让人兴奋、最吸引眼球的就是各种炫酷、新潮的功能。
更深入一点,我们关注的通常是功能。只要实现了功能,什么编码风格、代码格式等等都是无关紧要的细节,谁在乎呢?
什么? PEP8?你在说什么,请大声点,我听不见——
编码标准是什么?
俗话说“不守规矩,成不了圆”。
在编程实践中,代码标准就是“规则”;干净、可读和可维护的代码就是“方圆”。开发和协作的效率才是我们隐藏在层层之下真正追求的。
——当然,更抽象地说,如果代码是开发人员的作品,那么有的开发人员就是工匠,有的开发人员可以称为艺术家。
艺术家从哪里来?齐白石有句话:学我者生,似我者死。成为艺术家的道路是曲折的——废话哈哈。
首先,我们要学习前人留下的宝贵经验,从中汲取养分,为己所用。
为什么我们需要编码标准
不知道读者是否对各种代码文件格式感到困惑。
有多少种文件格式?只要看一下vscode支持的保存格式就可以看到这一点:
但实际上,它们的内容并没有本质的区别,都是“文本文件”。换句话说,它们都与纯文本文件和我们最常见的.txt 文件相同。这就是为什么世上总流传着“大师都用记事本编程”的轶事——在记事本里写一个.txt也是写,再写一个.c也是写,然后再写.py、.go , . java 和 .rs 有什么问题? “除了熟悉你的手之外什么都没有。”
也就是说,只要内容正确,即使文件后缀是.txt,也可以作为程序源文件。最直接的例子就是Python。
将以下内容保存为文件test_text.txt:
print("This is intterpreted from .txt")
然后在当前路径下执行命令行:
$ python test_text.txt
// This is intterpreted from .txt
可见,程序源文件的后缀并不影响Python解释器的解释。
更进一步,将 .txt 更改为 .cpp:
$ python test_text.cpps
// This is intterpreted from .cpp
众所周知,计算机对文本不太感兴趣。计算机内部存储的实际文本文件仍然是二进制数据,就像其他二进制文件一样。
那么我们为什么要费尽心思将程序源文件存储为文本文件呢?直接使用二进制不是很好吗?
是的。不香。
说白了,我们写程序不是为了让计算机读,而是为了别人甚至是为了我们自己——计算机只需要看到二进制就可以了。
计算机未使用的各种曲折的编码标准,对于人类来说,是一个整洁、完整、定义明确的“接口”,是人与人之间的“通信协议”。使用统一高效的通信协议可以大大降低开发者之间的通信成本,显着提高开发效率。
在网络通信中,通信协议有多么重要,那么在软件开发领域,编程规范有多么重要。
我总是忘记编程标准,pylint 可以为您提供帮助
说完编程标准的重要性,我们还需要面对一个现实问题:编程标准好不好,我们记不住。
是的,编程规范的内容就这么多。更不用说其他的了,光是 Python 语言就有各种增强提案(PEP)。许多提案都涉及编程风格的规范。即使你有过一段时间的实际开发经验,也不一定能真正把这些条目的内容一一记住。
这个时候,很自然的就会想到使用工具。幸运的是,现代的IDE甚至像vscode这样的编辑器都可以针对不同的编程语言提供相应的代码检查功能。勾选的不符合编程规范的项目会被下划线甚至高亮显示,提示开发人员进行修改。
但首先,这是一种被动的标准检查,可控性不强;其次,检查的内容可能不是很全面,难免有遗漏。
这里我想介绍的是一种主动检查代码规范的方法:使用pylint。
pylint的安装我就不详细说了。就像其他 Python 模块一样,只需 pip:
$ pip install pylint
安装后,使用起来非常简单,只需 pylint + [目标文件名]。
将以下文本保存为文件 justdopython.py:
def just():
print("just")
pass
def do():
print("dopython")
pass
然后执行命令:
$ pylint justdopython.py
// ************* Module justdopython
// test_text.py:11:0: C0304: Final newline missing (missing-final-newline)
// test_text.py:1:0: C0111: Missing module docstring (missing-docstring)
// test_text.py:1:0: C0111: Missing function docstring (missing-docstring)
// test_text.py:3:4: W0107: Unnecessary pass statement (unnecessary-pass)
// test_text.py:6:0: C0103: Function name "do" doesn't conform to snake_case naming style (invalid-name)
// test_text.py:6:0: C0111: Missing function docstring (missing-docstring)
// test_text.py:8:4: W0107: Unnecessary pass statement (unnecessary-pass)
// -------------------------------------------------------------------
// Your code has been rated at -1.67/10 (previous run: 0.00/10, -1.67)
逐一查看,可以看到输出内容首先列出了不符合规范的项目,并分别给出了与规范冲突的位置(列和行)、违反的规范编号以及违法行为的具体内容和类型。最后pylint也打分了源文件。
嗯,满分10分,我得了-1.67分……
请注意第一个不合格条目“最终换行符丢失”。 Python 编程标准建议我们在文件末尾留一个空行。
随后的“Missing module docstring”和“Missing function docstring”是由于缺少模块和函数的描述字符串造成的。我们可以根据需要添加;不仅方便快速了解相应的模块/功能,也可以用于后续的自动化。生成文档。
当然,有些人总是懒得写函数的描述文档。在这种情况下,可以使用特殊注释来禁止 pylint 检查某个规范:
def just(): # pylint: disable=missing-docstring
print("just")
pass
这样,如果使用pylint扫描源文件,这里就不再报相关冲突了。
再往下,还提醒我们,函数名“do”不符合蛇形命名风格——所谓蛇形命名,即所有小写单词都用下划线连接的命名风格,也是Python推荐的命名风格。
剩下的“Unnecessary pass statements”提示pass语句多余,只能修复。
最后需要提醒的是,虽然pylint可以通过注释或者配置文件取消某些标准提示。但还是建议尽量不要人为禁止相关提示。
有问题就需要解决,而不是假装问题不存在。
随着项目代码量的增加,修复前期遗留的小问题的成本会越来越高。