如何写出优质的python代码

写出来的代码,只要逻辑对了,就能运行,这使得一部分人对于代码质量不是很看重,代码读起来犹如天书。但总有一些追求卓越的人,精益求精,不只是代码性能高,可阅读性,可维护性同样很强。看他们的代码,就像是在欣赏一件艺术品,美轮美奂,字里行间都透着一股严谨专业的技术范。

你也想写出那种漂亮的代码么,本文总结了业内普遍认可的代码编写原则,规范,遵照这些原则和规范,你也可以写出专业级的代码。

1. 命名要有意义

无意义的命名,会影响代码的阅读,让人看得云里雾里

1.1 见其名,而知其意

好的变量名字,让人一眼便能大概猜的出它的作用,而糟糕的变量名字,虽然编写代码时省去了起名字的时间,但后续维护代码却不得不付出更多的时间。

stu_c = 10
stu_count = 10

stu_count 很容易被理解,它存储记录学生的数量,而stu_c就无法起到同样的效果,更不用说那些为了省事而用单个字母做变量的情况。

方法或函数的名称,尽量加上动词,比如下面的例子

def get_stu_name():
    pass

def set_stu_name():
    pass

def is_stu_pass():
    pass

类的名称,则使用名词短语,比如BankAccount, Book, HttpCode

1.2 避免误导

如果你在命名时,想通过名称传递一些信息,那么在使用过程中,一定要始终如一的坚持

stu_list = [('小明', 14), ('小刚', 15)]
# 经过一些操作后
stu_list = {
    '小明': 14,
    '小刚': 15
}

# 后续的使用中,非常容易把stu_list 当列表来使用

最初命名变量时,你期望通过名称传达一个信息,这个变量是列表类型,可是在随后的使用中,你不小心将其变为了字典,那么这就存在了误导,其他人可能继续将其当做一个列表来使用。

命名误导开发人员,更多的发生在函数和方法的命名上,比如我的另一篇讨论函数命名的文章为你的函数起一个好的名字 所提到的jieba模块的一个函数load_userdict, 这个函数名称让人一看到就以为需要传入一个字典,但实际情况却不是这样,你需要传入一个字符串或者一个file-like 类型的对象。

1.3 避免太短,或是太长

变量名称果断,根本起不到任何提示和辅助回忆的作用,而如果变量名称太长了,又会占用太多屏幕空间,同时也不利于阅读。使用驼峰命名,还是蛇形命名,这个要看个人喜好和一种编程语言默认的习惯。

1.4 避免在名称后面加数字

这种命名方式还是挺普遍的

count_1 = 20
count_2 = 10

def get_stu_info(id):
    pass
    
def get_stu_info_2(name):
    pass

count_1与count_2 都是用来计数的,可是一个1,一个2,这能表达什么呢?get_stu_info已经明确的表明函数是用来获取学生信息的,那么这个get_stu_info_2又是来做什么的呢?通常,如果两个函数功能很类似,但是参数不同,我会这样命名

def get_stu_info_by_id(id):
    pass
    
def get_stu_info_by_name(name):
    pass

2. 函数或方法要安全,简洁

2.1 单个函数代码行数不应过多

一个函数有100行代码,听起来只有100行,并不多,但一整个屏幕已经无法显示全部的函数代码了。当一个函数里的代码过多时,或者是功能不够单一,或者是一些本应该抽象出来单独作为一个函数的逻辑片段没有被抽象,总之,你写了一个非常糟糕的代码。

函数尽量短小,最好不要超过50行。

2.2 功能要单一,只做一件事情

功能越是单一,就越是安全,因为你修改一处代码时,需要额外考虑的条件就越少,你只需要关注这一小块逻辑即可。许多个功能,累加到一起,就实现了一个更大的功能,而这个实现更大功能的函数里,并没有太多的代码,都是对实现小功能函数的调用,这个时候,你就能感受得到函数功能单一的的魅力了。相比于所有代码都挤在一个函数里,你可以通过这些短小的函数更清楚的知道函数实现的步骤和细节,阅读代码的人会更有体会。

2.3 前置条件单独准备

其实这一点和函数功能要单一是相同的,只是从另一个角度进行了阐释。当你用unittest 模块对代码进行测试时,测试用例的编写需要定义一个类继承TestCase, 如果需要为测试准备一些条件,那么这些逻辑应当写在setUp方法中。这就是我所讲的前置条件单独准备。

一个函数,承诺只做一件事情,实现一个单一的功能,假如函数的执行需要一些条件,那么,这个条件最好不要在函数内部运行时准备,而是明确的放在函数外部准备。因为通常情况下,调用你函数的人不会事先完整的阅读你的代码,它并不清楚这个函数还做了一些额外的准备操作或者善后操作,这种情况下就容易引发意外,或者在函数使用出现问题时不知从何处着手解决问题。

2.4 被调用的函数放在后面

有时候,一个模块写了很多函数,几百行代码放在一起,尽快你遵守规则进行命名,阅读代码也是一件不易的事情。如果函数之间存在调用关系,那么就把他们放在一起,而且被调用的函数放在后面,这样,你在阅读代码时,很容易找到他们。

3. 关于注释

3.1 什么情况下需要注释,什么情况下不需要

  1. 如果函数很短小,且函数名称已经非常准确的表明了函数的功能作用,那么就没必要添加注释
  2. 如果函数里代码行数很多,即便函数名称遵守了规则,也应当添加注释
  3. 如果函数的参数很多,那么应当添加注释,至少得把这些参数解释清楚,否则调用函数的人不知道如何传递参数
  4. 关键的业务逻辑,或者特殊的逻辑分支,需要添加注释

3.2 好的注释

  1. 特殊的逻辑,要解释清楚来龙去脉,这种事情很常见,产品经理突然找到你,某种情况下,我们这么处理,对于这种特殊情况,请务必做好注释,否则将来维护代码的人根本不知道你这样写的缘由,也就根本不敢修改
  2. 如果有需要完善的地方,请写好 todo
  3. 多写为什么,少写是什么,是什么至少可以通过阅读代码来了解,但是为什么就是一个对阅读代码的人完全没有头绪的事情。
  4. 解释你的架构设计,并不是每个人都已经达到架构师的水平,如果你的代码设计的很精妙,用了许多高级语法和技术,请适当的做一些解释的工作,写代码是为了给别人看的,不是用来show的,代码里的奇技淫巧向来不受待见。

3.3 坏的注释

没有所谓坏的注释,只要不是错误的注释,在我看来都是好注释,即便注释写的驴唇不对马嘴,相比于完全没有注释的代码,我喜欢前者。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案