Python 简洁编码之道

62 阅读6分钟

640?wx_fmt=jpeg

640?wx_fmt=png

IGI

网易游戏运维专家, 10 年运维老司机, 负责网易游戏私有云平台的运维工作, 专注于运维技术能力的深入打磨, 专治运维界各类疑难杂症, 拥有强大的故障分析能力及丰富的故障解决经验.

随着互联网技术的发展, 现如今信息爆炸越来越明显, 大家在工作中需要接触及学习的技术点也是越来越多. 在这种大背景的情况下, 以号称「简洁」著称的 Python 语言自然而然火了起来.

那是不是只要使用 Python 来写代码, 就算「简洁」编码呢? 非也, 即使用同样的语言, 代码的「简洁」程度也是因人而异, 本文将结合生产环境中常见的代码写法进行讲解, 给大家拨开迷雾见云彩, 看透其中的奥秘.

何谓「简洁」编码?

在开始前, 先问大家一个问题, 什么样的代码算得上「简洁」?

这类问题, 其实也隐藏在我们的日常生活中, 这里我直接举个例子, 大家请看下面三句话

1. 家有千金, 行止由心.

2. 形若槁骸, 心如死灰.

3. 君莫欺我不识字,人间安得有此事.

大家看了上面三句话的第一眼是什么感觉? 用了古文的写法, 表达也非常到位, 可是大家细想, 在理解这三句话真正含义的时候, 是不是脑海里面有过短暂的消化和转化的时间? 大家再看以下三句话, 与上面三句话表达出同样的意思.

1. 有钱, 任性

2. 心好累

3. 我读书少,你不要骗我 

是不是一眼就能抓住这几句话的含义?

简短, 直观, 易于理解, 这就是「简洁」, 而符合这种特性的代码, 则为「简洁」的编码

简洁代码的思路讲解

接下来, 我将以下工作中常见的代码写法来讲解, 如何简洁化我们的 python 代码

注: 以下代码样例仅针对最常用的 python2 版本

1. 使用 dict 的默认操作符可以方便的获取到 key, 减少不必要的 dict.keys() 和 dict.has_key() 操作

  • 代码样例1

640?wx_fmt=png

  • 代码样例2

640?wx_fmt=png

2. 当需要同时获取字典的 key和 value 时, 可以使用 iteritems 迭代器

  • 代码样例3

640?wx_fmt=png

3. 文件的默认操作符也是类似的, 在循环时可以直接使用

  • 代码样例4

640?wx_fmt=png

小贴士1:
  • 如果类型支持, 就直接使用默认迭代器和操作符, 例如列表, 字典和文件. 默认操作符和迭代器简单高效, 没有额外的方法调用.

4. 尽可能使用隐式布尔值条件语句

  • 代码样例5

640?wx_fmt=png

  • 代码样例6

640?wx_fmt=png

  • 代码样例7

640?wx_fmt=png

小贴士 2:

  • Python 会在条件语句上下文中求布尔值. 按简单的直觉来讲, 就是所有的「空」值都被认为是 false. 因此 0,None, [], {}, “” 都被认为是 false. 使用 Python 布尔值的条件语句更易读也更不易犯错. 大部分情况下, 也更快.
  • 永远不要用 == 或者 != 来比较 None 和布尔值, 直接使用 if x: 代替, 如果需要区分 False 和 None, 可以使用 if x is None: 这样的语句.

5. 利用 set 和 list 简化多个条件语句的值判断

  • 代码样例8

640?wx_fmt=png

  • 代码样例9

640?wx_fmt=png

6. 利用 locals 函数或是 globals 函数可以更方便的完成多个变量的检查

  • 代码样例10

640?wx_fmt=png

7. 利用条件语句的取反(if not), 可以尽可能的减少复杂逻辑中的代码嵌套层级

  • 样例11改进前

640?wx_fmt=png

  • 样例11改进后

640?wx_fmt=png

写出「简洁」 Python 代码的学习资料

上面举了 11 个例子, 让大家有了真实的「简洁」思路, 那这些思路从何而来, 以下是我认为需要反复阅读并理解吸收的知识

1. 《Python之禅》

相信很多同学在学习 Python 的时候, 也看过箸名的 Python 之禅 , 像上面的样例 11, 改进前就是违背了扁平胜于嵌套的信条, 我们可以多在 review 自己代码时, 思考一下代码是不是违背了这些信条

640?wx_fmt=png

  • 优美胜于丑陋(以编写优美的代码为目标)
  • 明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)
  • 简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)
  • 复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)
  • 扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)
  • 间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)
  • 可读性很重要(优美的代码是可读的)
  • 即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)
  • 不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写 except:pass 风格的代码)
  • 当存在多种可能,不要尝试去猜测,而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)
  • 虽然这并不容易,因为你不是 Python 之父(这里的 Dutch 是指 Guido )
  • 做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)
  • 如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)
  • 命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)

注: 《Python 之禅》是 2004 年的 Python 改进提案,编号为 PEP 20。以禅诗、偈颂的形式。

2. PEP8 和 Google Python Style Guild

PEP8 一定要读几次, 有些规范记不住没关系, 可以多使用 pylint 检查工具来给检查代码,  Google Python Style Guild 也是非常值得大家熟读的

写在最后

读过这些信条和资料, 最重要还是自己要能保持不断优化自己代码的念头, 才能在一次次的编码过程中, 不断打磨自己的编码能力, 最终做到把「简洁」的理念深入自己的编码能力中.

多看多练多思考, 共勉~

640?wx_fmt=jpeg

▼ 点击成为社区注册会员 「在看」 一下,一起PY