注释是程序员在他们的代码中加入的注释,以解释该代码应该做什么。将代码转化为行动的编译器或解释器会忽略注释,但它们对管理软件项目是必不可少的。
注释有助于向其他程序员解释你的 Python 代码,并且可以提醒你为什么做出这样的选择。注释通过帮助未来的程序员理解软件背后的设计选择,使调试和修改代码更加容易。
尽管注释主要是为开发人员准备的,但编写有效的注释也可以帮助为你的代码的用户制作优秀的文档。在Python项目的Sphinx等文档生成器的帮助下,你的代码中的注释可以为你的文档提供内容。
让我们来看看Python中的注释是怎样的。
Python中的注释
根据Python PEP 8样式指南,在写注释时有几件事需要注意:
- 注释应该始终是完整而简明的句子。
- 没有注释总比有一个难以理解或不准确的注释要好。
- 注释应该定期更新,以反映你的代码的变化。
- 太多的注释会使人分心并降低代码质量。如果代码的目的很明显,就不需要注释。
在Python中,当一行以 #
符号开始时,它就被声明为注释。当Python解释器在你的代码中遇到 #
时,它将忽略该符号之后的任何内容,并且不会产生任何错误。有两种方法来声明单行注释:内联注释和块注释。
内联注释
内联注释提供了对变量和简单操作的简短描述,与代码语句写在同一行。
border = x + 10 # Make offset of 10px
注释在与代码相同的语句中解释了代码的功能。
区块注释
区块注释用于描述代码中的复杂逻辑。Python 中的块状注释的构造与内联注释类似 – 唯一的区别是块状注释是写在单独的一行上。
import csv from itertools import groupby # Get a list of names in a sequence from the csv file with open('new-top-firstNames.csv') as f: file_csv = csv.reader(f) # Skip the header part: (sr, name, perc) header = next(file_csv) # Only name from (number, name, perc) persons = [ x[1] for x in file_csv] # Sort the list by first letter because # The groupby function looks for sequential data. persons.sort(key=lambda x:x[0]) data = groupby(persons, key=lambda x:x[0]) # Get every name as a list data_grouped = {} for k, v in data: # Get data in the form # {'A' : ["Anthony", "Alex"], "B" : ["Benjamin"]} data_grouped[k] = list(v)
注意,当使用块状注释时,注释是写在它们所解释的代码上面的。Python PEP8 风格指南规定,一行代码不应包含超过79个字符,而内联注释常常使行数超过这个长度。这就是为什么要写块状注释,在不同的行中描述代码。
多行注释
Python 本身并不支持多行注释,这意味着没有专门的规定来定义它们。尽管如此,跨越多行的注释经常被使用。
你可以通过在每一行前面加上 #
来创建一个多行注释,而不是几个单行注释。
# interpreter # ignores # these lines
你也可以使用多行字符串的语法。在Python中,你可以用 """
,三个双引号,或 '''
,三个单引号包围它们来定义多行字符串。
print("Multi-Line Comment") """ This String is Multi line """
在上面的代码中,多行字符串没有分配给一个变量,这使得这个字符串像一个注释一样工作。在运行时,Python 忽略了这个字符串,它不会被包含在字节码中。执行上面的代码会产生下面的输出。
Multi-Line Comment
特殊注释
除了使你的代码具有可读性外,注释在Python中还有一些特殊的作用,如计划未来的代码添加和生成文档。
Python文档串注释
在 Python 中,docstrings 是多行注释,解释如何使用一个给定的函数或类。通过创建高质量的 docstrings,可以改善你的代码的文档。当使用一个函数或类并使用内置的 help(obj)
函数时,docstrings 可能有助于给出对象的概况。
Python PEP 257 提供了一种在 Python 中声明 docstrings 的标准方法,如下所示:
from collections import namedtuple Person = namedtuple('Person', ['name', 'age']) def get_person(name, age, d=False): """ Returns a namedtuple("name", "age") object. Also returns dict('name', 'age') if arg `d` is True Arguments: name – first name, must be string age – age of person, must be int d – to return Person as `dict` (default=False) """ p = Person(name, age) if d: return p._asdict() return p
在上面的代码中,docstring提供了相关函数工作的细节。通过像Sphinx这样的文档生成器,这个docstring可以用来给你项目的用户一个如何使用这个方法的概述。
一个定义在函数或类签名下面的文档串也可以通过使用内置的 help()
函数返回。 help()
函数接受一个对象或函数名称作为参数,并将函数的文档串作为输出返回。在上面的例子中,可以调用 help(get_person)
来显示与 get_person
函数相关的文档串。如果你在交互式 shell 中使用 -i
标志运行上面的代码,你可以看到这个 docstring 将如何被 Python 解析。通过输入 python -i file.py
来运行上面的代码。
在命令行界面中解析的Python文档串注释
help(get_person)
函数调用返回你的函数的文档串。输出包含 get_person(name, age, d=False)
,这是一个 Python 自动添加的函数签名。
get_person.__ doc__
属性也可以被用来以编程方式检索和修改 docstring。在上面的例子中添加了 “一些更多的新信息 “之后,它出现在对 help(get_person)
的第二次调用中。尽管如此,你不太可能需要像这样在运行时动态地改变 docstrings。
TODO注释
在编写代码时,有时你会想突出某些行或整个块来进行改进。这些任务是由TODO注释来标记的。当你计划更新或修改你的代码时,或者当你想通知项目的用户或合作者文件的特定部分的代码还没有写完时,TODO注释就会很方便。
TODO注释不应该被写成伪代码–它们只需要简单地解释尚未编写的代码的功能。
TODO注释和单行块注释非常相似,它们之间唯一的区别是TODO注释必须以TODO前缀开始。
# TODO Get serialized data from the CSV file # TODO Perform calculations on the data # TODO Return to the user
值得注意的是,尽管许多 IDE 可以为程序员突出显示这些注释,但 Python 解释器对 TODO 注释的看法与块注释没有任何区别。
编写Python注释时的最佳做法
在编写注释时,有一些最佳实践应该被遵循,以确保可靠性和质量。下面是在Python中编写高质量注释的一些提示。
避免脱裤子放屁
那些陈述明显的注释并没有给你的代码增加任何价值,应该避免使用。比如说:
x = x + 4 # increase x by 4
这条注释并不有用,因为它只是简单地说明了代码的作用,而没有解释为什么需要这样做。注释应该解释 “为什么”,而不是它们所描述的代码的 “什么”。
改写后更有用,上面的例子可能是这样的:
x = x + 4 # increase the border width
保持Python注释简明扼要
保持你的注释简短而容易理解。它们应该用标准的散文来写,而不是用伪代码来写,并且应该取代阅读实际代码的需要,以获得对代码的总体概述。太多的细节或复杂的注释并不能使程序员的工作变得更容易。比如说:
# return area by performing, Area of cylinder = (2*PI*r*h) + (2*PI*r*r) def get_area(r,h): return (2*3.14*r*h) + (2*3.14*r*r)
上面的注释为读者提供了更多的信息,而不是必要的信息。注释应该提供代码的一般总结,而不是指定核心逻辑。这条注释可以改写为
# return area of cylinder def get_area(r,h): return (2*3.14*r*h) + (2*3.14*r*r)
谨慎地使用标识符
在注释中应谨慎使用标识符。改变标识符的名称或情况会使读者感到困惑。例如:
# return class() after modifying argument def func(cls, arg): return cls(arg+5)
上面的注释提到了 class
和 argument
,但这两者在代码中都没有找到。这条注释可以改写为:
# return cls() after modifying arg def func(cls, arg): return cls(arg+5)
DRY和WET原则
当你写代码时,你要坚持DRY(不要重复自己)原则,避免WET(把所有东西都写两次)。
这对注释来说也是如此。避免使用多个语句来描述你的代码,并尽量将解释相同代码的注释合并为一个注释。然而,在合并注释的时候一定要小心:不小心合并多个注释会导致一个巨大的注释,违反了风格指南,而且读者很难理解。
记住,注释应该减少代码的阅读时间。
# function to do x work def do_something(y): # x work cannot be done if y is greater than max_limit if y < 400: print('doing x work')
在上面的代码中,注释是不必要的零散的,可以合并成一个注释。
# function to do x if arg:y is less than max_limit def do_something(y): if y in range(400): print('doing x work')
一致的缩进
确保注释的缩进程度与它们所描述的代码相同。如果不这样做,就很难理解。
例如,这个注释的缩进和定位都不正确:
for i in range(2,20, 2): # only even numbers if verify(i): # i should be verified by verify() perform(x)
它可以改写成如下样子:
# only even numbers for i in range(2,20, 2): # i should be verified by verify() if verify(i): perform(x)
小结
注释是编写可理解代码的一个重要组成部分。你在写注释方面的投资是你未来的自己–或其他需要在你的代码库上工作的开发者–会欣赏的。注释还可以让你对你的代码有更深入的了解。
在本教程中,你已经了解了更多关于Python中的注释,包括各种类型的Python注释,何时使用每种注释,以及创建注释时应遵循的最佳实践。
写好注释是一种需要学习和发展的技能。为了练习写注释,可以考虑回头将注释添加到你以前的一些项目中。为了获得灵感和看到最佳实践,请查看GitHub上记录良好的Python项目。
评论留言