如何在 Python 中编写简洁代码
究竟什么是“整洁代码”?一般来说,整洁代码是指易于理解、易于修改或维护的代码。
由于代码更多的是被阅读而不是编写,因此编写简洁代码的实践对我们的职业生涯至关重要。
今天,我将分享一些我多年来积累的技巧,并给出一些 Python 示例。
也就是说,这些原则通常适用于大多数编程语言。
太长不看
- 命名事物时要保持一致。
- 命名事物时要避免产生混淆。
- 避免使用双重否定。
- 编写能够自我解释的代码
- 请勿滥用评论
1. 正确命名事物
避免任何混淆的可能性
尽管这是最古老的技巧,但却是我们最常忘记的简单规则。在命名文件夹、函数或变量之前,务必问问自己:“如果我这样命名,它会不会有别的意思,或者会让其他人感到困惑?”
这里的总体思路是在命名任何事物时都要避免任何混淆的可能性。
# For example, you're naming a variable that represents the user’s membership:
# Example 1
# ^^^^^^^^^
# Don't
expired = True
# Do
is_expired = True
# Example 2
# ^^^^^^^^^
# Don't
expire = '2021-04-17 03:25:37.403283'
# Do
expiration_date = '2021-04-17 03:25:37.403283' # OR
expiration_date_string = '2021-04-17 03:25:37.403283'
之所以说expired这个名字不太理想,是因为expired它本身含义模糊。新来的开发人员无法确定它代表的expired是日期还是布尔值。
命名要保持一致
在团队项目中保持一致性至关重要,可以避免混淆和疑虑。这适用于变量名、文件名、函数名,甚至目录结构。
任何名称都不应仅凭个人喜好决定。在修改任何内容之前,务必先查看其他人已写的内容并进行讨论。
# For example if the existing project names a Response object as "res" already:
# Existing functions
# ^^^^^^^^^^^^^^^^^^
def existing_function(res, var):
# Do something...
pass
def another_existing_function(res, var):
# Do something...
pass
# Example 1
# ^^^^^^^^^
# Don't
def your_new_function(response, var):
# Do something...
pass
# Do
def your_new_function(res, var):
# Do something...
pass
选择名字时的额外提示
- 变量是名词(即
product_name)。 - 执行某项操作的功能是动词(即
def compute_user_score())。 - 布尔变量或返回布尔值的函数是疑问句(即
def is_valid())。 - 名称应具有描述性,但不要过于冗长(例如,
def compute_fibonacci()而不是def compute_fibonacci_with_dynamic_programming())。
2. 避免双重否定
“你能确保之后不要忘记关灯吗?”
哎。所以,我到底该不该关灯呢?等等,让我再读一遍。
我们不妨达成共识:双重否定确实令人困惑。
# Example to check if a user's membership is valid or not:
# Don't
is_invalid = False
if not is_invalid:
print("User's membership is valid!")
# Do
is_valid = True
if not is_valid:
print("User's membership is invalid!")
如果你需要读不止一遍才能确定,那它就有问题。
3. 编写自解释代码
我记得以前有人告诉工程师,应该在代码中到处添加注释来“提高代码质量”。
那种日子早已一去不复返了。如今,工程师需要编写易于理解、无需过多解释的代码。例如,我们应该尝试将复杂的逻辑用描述性强、易于理解的变量来表示。
# Don't write long conditionals
if meeting and (current_time > meeting.start_time) and (user.permission == 'admin' or user.permission == 'moderator') and (not meeting.is_cancelled):
print('# Do something...')
# Do capture them in many variables that reads like English
is_meeting_scheduled = meeting and not meeting.is_cancelled
has_meeting_started = current_time > meeting.start_time
has_user_permission = user.permission == 'admin' or user.permission == 'moderator'
if is_meeting_scheduled and has_meeting_started and has_user_permission:
print('# Do something...')
请勿滥用评论
就像代码本身一样,注释也会过时。
人们常常忘记在代码重构时更新注释。在这种情况下,注释本身就会间接地成为造成混乱的根源。
每当你觉得需要写注释时,都应该重新评估你编写的代码,看看如何才能让它更清晰易懂。
何时撰写评论的示例
我会考虑使用注释的场景之一是需要进行切片操作的时候。这会引发诸如“为什么我们要这样做?为什么不使用其他索引?”之类的问题。
# Example of getting an email returned from a 3rd party API:
# Example 1
# ^^^^^^^^^
# Do
raw_string = get_user_info()
email = raw_string.split('|', maxsplit=2)[-1] # NOTE: raw_string e.g. "Magic Rock|jerry@example.com"
另一个例子:
# Example of a function calling a random time.sleep():
# Example 2
# ^^^^^^^^^
# Don't
def create_user(user_ids):
for id in user_ids:
make_xyz_api_request(id)
time.sleep(2)
想象一下,你是一名新手开发者,第一次看到上面的代码。
我首先想到的是“为什么我们每次发出请求都要随机等待两秒钟?”
原来编写这段代码的原开发者只是想让我们限制向第三方 API 发送的请求数量。
# Do
def create_user(user_ids):
for id in user_ids:
make_xyz_api_request(id)
time.sleep(2) # NOTE: service 'xyz' has a rate limit of 100 requests/min, so we should slow our requests down
永远要站在他人的角度思考(例如,“别人会如何理解我的代码?”)。如果你对列表进行切片或使用特定索引(例如array[3]),没有人会确切地知道你为什么要这样做。
我该如何运用这些知识?
没有人能从一开始就写出简洁的代码。事实上,每个人一开始都会写一些“糟糕”或“丑陋”的代码。
就像生活中大多数事情一样,要想擅长某件事,就必须反复练习,投入时间。
除了练习之外,以下方法对我有用:
- 不断问自己一些问题,例如“有没有更好的表达方式?这样写会不会让别人感到困惑?”
- 参与代码审查。
- 探索其他编写良好的代码库。如果您想了解一些编写精良、简洁且符合 Python 风格的代码示例,请查看 Python requests库。
- 与人交谈、讨论或交流意见,你会学到更多东西。
最后想说的话
编写简洁代码很难向很多非技术人员解释,因为在他们看来,这似乎对公司的业务影响几乎没有直接价值。
编写简洁的代码也需要花费大量的时间和精力,而这两个因素都会转化为企业的成本。
然而,从长远来看,代码库中保持代码的整洁对工程师至关重要。有了更整洁的代码库,工程师就能更快地交付代码和部署应用程序,从而更好地实现业务目标。
除此之外,编写干净的代码至关重要,这样新的合作者或贡献者在开始新项目时就能更快地上手。
参考
本文最初发表于jerrynsh.com 网站。
文章来源:https://dev.to/jerrynsh/how-to-write-clean-code-in-python-2pf3