在讲解 Python 的编程规范之前,我认为有必要让大家了解一下目前主流的编程规范有哪些
目前对于Python主流的编程规范指南,有大名鼎鼎的 PEP 8 指南 以及 Google 开源项目风格指南
编程规范真的是很重要,特别对于正在从事程序员或即将从事程序员的人来说。我们并不是只是一个人在敲代码,如果你的代码风格和其他的程序员的相同,那么就能够更加顺利地与大家一起做项目,这套代码风格理应是编程规范,采用一致的风格可以使代码更易读、更易懂。
如果编程规范不佳,那会极大影响到其他人阅读这份代码的效率,评价一个程序员的能力往往是从代码这第一印象开始的,这就与写字一样,好的程序员肯定是会注重代码规范的
即便代码只是给自己去看,也应该按照编程规范风格来写,以便日后修改时容易阅读一些
在下面的内容中,将以PEP 8 风格指南为主,Google 开源项目风格指南为辅并标注进行讲解
PEP 8 是 Python Enhancement Proposal #8 的简写,中文释义Python的增强提议,它是一份针对 Python 代码格式而编订的风格指南,完整指南网址:https://www.python.org/dev/peps/pep-0008/
Python 开发界用 Pythonic 这个词形容具有特定风格的代码,这种风格是大家在使用Python语言及合作的过程中约定俗成的一种习惯,Python的开发者不喜欢写复杂的代码,会使用直观、简洁且容易看懂的方式去编写程序
说到谷歌,不会没有人不知道吧,大名鼎鼎的安卓系统就是谷歌公司研发的,中文版的 《Google 开源项目风格指南》 现有五份风格指南,分别是:
这此指南中有这么一段:
每个较大的开源项目都有自己的风格指南,关于如何为该项目编写代码的一系列约定 (有时候会比较武断).。当所有代码均保持一致的风格, 在理解大型代码库时更为轻松。
在Python中, 空白(whitespace)在语法上相对重要。空白会影响代码的清晰程度,遵守有关于空白的建议有助于提高阅读效率。
# 正确的
spam(ham[1], {"eggs": 2}, [])
# 错误的
spam( ham[ 1 ], { "eggs": 2 }, [ ] )
string = ("这是一个非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长"
"非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长的字符串")
PEP 8 建议采用不同的方式给Python代码中的各个部分命名,这样在阅读代码时,就可以根据这些名称看出它们在Python语言中的角色。
函数、变量及属性用小写字母来拼写,各单词之间用下划线相连,列如:lowercase_underscore
受保护的实例属性,用一个下划线开头,列如:_leading_underscore
单个下划线前缀有一个约定俗成的含义,那就是告诉程序员以单个下划线开头的变量或方法仅供内部使用,对于类中的属性,单个下划线并没有阻止我们“进入”类并访问该变量的值,但前导下划线的确会影响从模块中导入属性
# 这是module_A.py文件
def external_func():
return 23
def _internal_func():
return 42
>>> from my_module import *
>>> external_func()
23
>>> _internal_func()
NameError: "name '_internal_func' is not defined"
私有的实例属性,用两个下划线开头,列如:__double_leading_underscore
Python解释器会重写属性名称,以避免子类中的命名冲突,作为一个类私有的属性,外部无法直接通过 __属性名
形式对该属性进行访问,但并没有真正意义上的限制我们从外部访问该属性,可以理解成只是将其隐藏,以_类名__属性
格式拼接即可访问
class Test:
def __init__(self):
self.attr = 1024
self.__attr_A = "hello"
self.__attr_B = "world"
def __func(self):
return self.__attr_B
>>> test = Test()
>>> test.attr
1024
>>> test.__attr_A
AttributeError: 'Test' object has no attribute '__attr_A'
>>> test.__func()
AttributeError: 'Test' object has no attribute '__func'
>>> test._Test__attr_A
'hello'
>>> test._Test__func()
'world'
类(包括异常)命名时,每个单词的首字母均大写,列如:CapitalizedWord
模块级别的常量,所有的字母都大写,各单词之间用下划线相连接,列如:ALL_CAPS
类中的实例方法,应该把第一个参数命名为self
,用来表示该对象本身
类方法的第一个参数,应该命名为cls
,用来表示这个类本身
The Zen of Python(Python之禅) 中提到:“每件事都应该有简单的做法,而且最好只有一种”。PEP 8 就试着运用这个理念,来规范表达式和语句的写法
采用行内否定,即把否定词直接写在要否定的内容前面,而不要放在整个表达式的前面,列如应该写 if a is not b
,而本身if not a is b
不要通过长度判断容器或序列是不是为空的,列如不要通过if len(somelist) == 0
判断somelist
是否为 []
或 ""
等空值,而是应该采用if somelist
语句,因为Python会把非空的值自动判定为True
不要把if
语句、for
循环、while
循环及except
复合语句挤在一行。应该把这些语句分成多行来写,这样更加清晰
推荐使用with
语句管理文件,显式的关闭文件,节省系统资源和避免代码操作文件后的其他文件操作问题,以及对文件的意外引用(Google)
with open("hello.txt", "r") as f_r:
for line in f_r:
# 循环打印每一行
print(line)
如果表达式一行写不下,可以用括号括起来,而不要用 \ 符号续航
反斜线有时也仍然合适,列如长with
语句时不能使用括号括起来延续,所以反斜杠是可以接受的
with open('/path/to/some/file/you/want/to/read') as file_1, \
open('/path/to/some/file/being/written', 'w') as file_2:
file_2.write(file_1.read())
PEP 8 对于怎样在代码中引入并使用模块,给出了下面几条建议
引入每个模块应该独占一行
# 正确的
import os
import sys
# 错误的
import os, sys
import
语句(含 from x import y)总是应该放在文件开头
引入模块是,总是应该使用绝对名称,而不应该根据当前模块路径来使用相对名称。列如,要引入bar
包中的foo
模块,应该完整地写出from bar import foo
,即便当前的路径为bar
包里,也不应该简写为import foo
如果一定要用相对名称来编写 import 语句,那就应该明确地写成:from . import foo
文件中的import
语句应该按顺序划分为三个部分:首先引入标准库里的模块,然后引入第三方模块,最后引入自己的模块,属于同一个部分的import
语句按字母顺序排列
import this
在导入这一个神秘标准库后,控制台会打印这么一段来自 Tim Peters 的文章
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
将其进行翻译
Beautiful is better than ugly.
# 优美胜于丑陋(Python以编写优美的代码为目标)
Explicit is better than implicit.
# 明了胜于晦涩(优美的代码应当是明了的,命名规范,风格相似)
Simple is better than complex.
# 简洁胜于复杂(优美的代码应当是简洁的,不要有复杂的内部实现)
Complex is better than complicated.
# 复杂胜于凌乱(如果复杂不可避免,那代码间也不能有难懂的关系,要保持接口简洁)
Flat is better than nested.
# 扁平胜于嵌套(优美的代码应当是扁平的,不能有太多的嵌套)
Sparse is better than dense.
# 间隔胜于紧凑(优美的代码有适当的间隔,不要奢望一行代码解决问题)
Readability counts.
# 可读性很重要(优美的代码是可读的)
Special cases aren't special enough to break the rules.
Although practicality beats purity.
# 即便假借特例的实用性之名,也不可违背这些规则(这些规则至高无上)
Errors should never pass silently.
Unless explicitly silenced.
#不要包容所有错误,除非你确定需要这样做(精准地捕获异常,不写except:pass风格的代码)
In the face of ambiguity, refuse the temptation to guess.
# 当存在多种可能,不要尝试去猜测
There should be one-- and preferably only one --obvious way to do it.
# 而是尽量找一种,最好是唯一一种明显的解决方案(如果不确定,就用穷举法)
Although that way may not be obvious at first unless you're Dutch.
# 虽然这并不容易,因为你不是 Python 之父(这里的Dutch是指Guido)
Now is better than never.
Although never is often better than *right* now.
# 做也许好过不做,但不假思索就动手还不如不做(动手之前要细思量)
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
# 如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然(方案测评标准)
Namespaces are one honking great idea -- let's do more of those!
# 命名空间是一种绝妙的理念,我们应当多加利用(倡导与号召)
Python 本身就是一个简洁又极其优美的语言,通过这些如诗一般的文字充分透露出python编程之美,而这些文章就是大名鼎鼎的python之禅(The Zen of Python)
由衷感谢