编写干净的 Python 代码就是要使其尽可能易于理解且简洁。后期便于维护,代码约简洁越好维护,bug就越好排查。
使用 str.join() 而不是 for 循环
在 Python 中连接字符串最直接的方法是使用+ 运算符:
hat_description = hat.colour + hat.type
当您将少量字符串连接在一起时,这非常好(尽管 f 字符串是处理更复杂字符串的最佳选择)。
当它们用于连接大型字符串列表时,就会出现使用+or的问题+=。例如,您可以像这样在 for 循环中使用它们:
all_hats = ""
for hat in my_wardrobe.hats:
all_hats += hat.description
这读起来很麻烦,而且性能也不是很好。必须为 for 循环中的每次迭代创建一个新字符串,这会减慢速度。
幸运的是,Python 字符串提供了join解决这个问题的方法。
all_hats = "".join(hat.description for hat in my_wardrobe.hats)
这在一行中完成了相同的任务,并且启动速度要快得多。您还可以轻松地在每个字符串之间添加分隔符,而不必担心在结果的开头或结尾添加额外的分隔符。
all_hats = ", ".join(hat.description for hat in my_wardrobe.hats)
合并 isinstance 调用
一个小技巧——当你想检查某物是否是多种不同类型中的一种时,而不是这样:
if isinstance(hat, Bowler) or isinstance(hat, Fedora):
self.wear(hat)
您可以将呼叫合并为:
if isinstance(hat, (Bowler, Fedora)):
self.wear(hat)
这更短,同时保持美观且易于阅读。
用最小/最大调用替换比较
我们经常需要计算出两个值中的最小值或最大值,并且可能会想到使用这样的模式来做到这一点:
if first_hat.price < second_hat.price:
cheapest_hat_price = first_hat.price
else:
cheapest_hat_price = second_hat.price
更快的方法在Python做,这是使用内置的min和max功能。此代码是实现相同结果的更短更清晰的方法:
cheapest_hat_price = min(first_hat.price, second_hat.price)
当我们想在变量值上设置上限或下限时,相同的函数提供了一种快捷方式:
前:
if sale_price >= 10:
sale_price = 10
后:
sale_price = min(sale_price, 10)
用下划线替换未使用的索引
有时在 for 循环中,我们只希望某些代码运行一定次数,而实际上并不使用索引变量。
例如拿这个代码:
for hat in my_wardrobe.hats:
self.shout("Hurrah!")
我们引入了一个新变量,hat,在阅读代码时需要注意,但实际上我们不需要它,可以将其替换为_:
for _ in my_wardrobe.hats:
self.shout("Hurrah!")
Python 中的一个约定是_用作未使用变量的一次性名称。这意味着您的大脑可以学会安全地忽略这些,从而减少理解代码的开销。当您在for循环中看到这一点时,您会立即清楚该循环仅用于重复代码块,我们不关心正在迭代的值。
简化序列比较的测试
编码时一个非常常见的要求是在对其进行一些处理之前检查序列(字符串、列表或元组)是否为空。一种直接的方法是使用len内置函数,如下所示:
if len(my_wardrobe.hats) == 0:
self.shout("Alarm!")
然而,有一种更短、更 Pythonic 的方式来做到这一点,这是PEP 8 中给出的风格建议之一。这是为了利用在 Python 中,空序列的计算结果为False. 这意味着您可以像这样重写上面的内容:
if not my_wardrobe.hats:
self.shout("Alarm!")
具有至少一个元素的序列的等价情况是:
if len(my_wardrobe.hats) > 0:
self.shout("I have hats!")
这可以变成这个,因为这些评估为True:
if my_wardrobe.hats:
self.shout("I have hats!")
这种简化需要少量时间来适应,但是一旦您适应了它,代码就会非常自然地阅读。
将重复的条件提升到它自己的 if 语句中
在阅读代码时,你经常会看到这样的模式:
if isinstance(hat, Sombrero) and hat.colour == 'green':
self.wear(hat)
elif isinstance(hat, Sombrero) and hat.colour == 'red':
destroy(hat)
这种条件之一的重复使事情变得更难阅读,并伴随着代码重复的所有常见问题。虽然通常我们会尽量避免在代码中添加嵌套,但在这种情况下,将重复的条件提升到自己的if语句中是有意义的:
if isinstance(hat, Sombrero):
if hat.colour == 'green':
self.wear(hat)
elif hat.colour == 'red':
destroy(hat)
现在一目了然,整个if…elif链条只与阔边帽相关,与其他类型的帽子无关。