Python重构 - 第4部分

48 篇文章 1 订阅
17 篇文章 0 订阅

编写干净的 Python 代码就是要使其尽可能易于理解且简洁。后期便于维护,代码约简洁越好维护,bug就越好排查。

将重复的代码提取到一个方法中

不要重复自己 (DRY) 是编写干净、可维护代码的重要原则。重复的代码使代码库膨胀,使其更难阅读和理解。它也经常导致错误。如果仅在某些重复区域中进行更改,则经常会出现意外行为。
消除重复的主要方法之一是将公共区域提取到另一种方法中并调用它。

def extraction_example():
    self.speed_slider = Scale(
        self.master, from_=1, to=10, orient=HORIZONTAL, label='Speed'
    )
    self.speed_slider.pack()
    self.speed_slider.set(DEFAULT_SPEED)
    self.speed_slider.configure(background='white')

    self.force_slider = Scale(
        self.master, from_=1, to=10, orient=HORIZONTAL, label='Force'
    )
    self.force_slider.pack()
    self.force_slider.set(DEFAULT_FORCE)
    self.force_slider.configure(background='white')

在这里您可以看到创建滑块的代码重复了两次。在每种情况下,Scale 都会创建对象,然后对其调用相同的三个方法,并带有一些不同的参数。
您可以将其提取到这样的方法中:

def extraction_example():
    self.speed_slider = create_slider(self, 'Speed', DEFAULT_SPEED)
    self.force_slider = create_slider(self, 'Force', DEFAULT_FORCE)


def create_slider(self, label, default_value):
    result = Scale(self.master, from_=1, to=10, orient=HORIZONTAL, label=label)
    result.pack()
    result.set(default_value)
    result.configure(background='white')

    return result

原来的方法现在更短更清晰,新方法专注于做一件事——创建一个滑块。
如果稍后需要更多滑块,则create_slider可以调用该方法而不是再次复制代码。此外,如果滑块的创建方式发生变化,我们只需要在一个地方更改代码,而不是两个或多个。
识别在哪里可以提取重复的,或更常见的几乎重复的代码到自己的方法中,这是学习提高代码质量的关键技能。

简化布尔变量的赋值

我们在设置布尔变量的值时经常看到的一种模式是这样的(这两个代码片段是等效的):

if hat_string.startswith('hat'):
    starts_with_hat = True
else:
    starts_with_hat = False
starts_with_hat = True if hat_string.startswith('hat') else False

目的是设置starts_with_hat为Trueifhat_string.startswith(‘hat’) 返回True,False如果它返回False
这可以通过直接从函数调用中设置变量来更直接地完成。为此,您必须确保它返回一个布尔值!

starts_with_hat = hat_string.startswith('hat')

这更短,同时保持美观且易于阅读。

直接使用列表、集合或字典推导式,而不是调用 list()、dict() 或 set()

从生成器创建列表、集合或字典的 Pythonic 方法是使用推导式。
这可以用于列表、集合和字典:
前:

squares = list(x * x for x in y)
squares = set(x * x for x in y)
squares = dict((x, x * x) for x in xs)

后:

squares = [x * x for x in y]
squares = {x * x for x in y}
squares = {x: x * x for x in xs}

使用理解而不是方法稍微短一些,尤其是字典理解以理解形式更容易阅读。
推导式的性能也略高于调用方法。

使用推导式过滤而不是复制和删除

我们有时看到的一种模式是通过复制和删除不需要的元素来创建过滤集合。

my_hats = {'bowler': 1, 'sombrero': 2, 'sun_hat': 3}
for hat in my_hats.copy():
    if hat not in stylish_hats:
        del my_hats[hat]

使用理解是实现相同目标的更好方法。

my_hats = {'bowler': 1, 'sombrero': 2, 'sun_hat': 3}
my_hats = {hat: value for hat, value in my_hats.items() if hat in stylish_hats}

这样做可以让您定义想要在输出集合中包含的内容,而不是删除不需要的内容。这比for循环版本更自然。

a is not b和a not in b及not a is b和not a in b的比较

一个技巧是,它更容易阅读,读起来更像是英文散文,如果你写的not in和is not,而不是否定整个in或is表达。
前:

if not hat in hats:
    scream("Where's my hat?")
if not hat is None:
    scream("I have a hat!")

后:

if hat not in hats:
    scream("Where's my hat?")
if hat is not None:
    scream("I have a hat!")
来自 if 的提升循环

如果在条件的所有分支中都定义了相同的fororwhile循环,则可以通过提升来显着缩短和澄清代码。我们可以有一个循环并在循环内移动所有分支,而不是在每个分支内循环。

def sing_song(choice):
    style = STYLES[choice]
    if style == 'classical':
        while i_like_singing():
            sing_opera()
    elif style == 'folk':
        while i_like_singing():
            sing_folk_song()
    elif style == 'rock':
        while i_like_singing():
            sing_rock_ballad()

例如,上面的代码可以缩短为如下:

def sing_song(choice):
    style = STYLES[choice]
    while i_like_singing():
        if style == 'classical':
            sing_opera()
        elif style == 'folk':
            sing_folk_song()
        elif style == 'rock':
            sing_rock_ballad()

通过这样做,我们删除了两行重复的代码,并使代码的意图更加清晰。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值