一个程序之所以能自动做很多任务,是因为我们给他做好了条件判断。项目中,我们难免会使用if/else
判断逻辑语句。对简单的情况而言,使用逻辑语句会很清晰简洁,而项目情况一旦复杂,或者判断层次变多,盲目的使用if/else
语句就不免会显得难看,而且难以维护和扩展。
比如一个返回今天是什么日子的函数:
def get_today(today):
if today == 'Monday':
return '星期一'
elif today == 'Tuesday':
return '星期二'
elif today == 'Wednesday':
return '星期三'
elif today == 'Thursday':
return '星期四'
elif today == 'Friday':
return '星期五'
elif today == 'Saturday':
return '星期六'
elif today == 'Sunday':
return '星期日'
return '其他'
这样写虽然没有问题,但是如果现在要多加一个节日,这样我们就又要在现有逻辑中去加一条elif
逻辑语句。这样发展下去,代码不仅排版冗长难看,而且增加了修改逻辑语句的风险。
表驱动法
表驱动法是一种编写代码的策略,对于复杂的判断逻辑,尽量从表里查找信息而不使用逻辑语句。对于上面的代码,我们可以使用表驱动法,改为:
days = {
'Monday': '星期一',
'Tuesday': '星期二',
'Wednesday': '星期三',
'Thursday': '星期四',
'Friday': '星期五',
'Saturday': '星期六',
'Sunday': '星期日'
}
def get_today(today):
if today in days:
return days.get(today)
return '其他'
这样我们实际上就将数据和逻辑分离了,好处是数据和逻辑一目了然,维护和扩展更加简单。如果我们需要再加一个节日,只需要在数据中加,不需要去修改逻辑。
days = {
# ...
'New Year': '春节'
}
更复杂的嵌套
如果我们现在需要把星期和节日区分开,让他们返回不同的信息。
days = {
'Monday': '星期一',
'Tuesday': '星期二',
'Wednesday': '星期三',
'Thursday': '星期四',
'Friday': '星期五',
'Saturday': '星期六',
'Sunday': '星期日',
'New Year': '春节',
'Birthday': '生日'
}
def get_today(today):
if today in days:
result = days.get(today)
if result.startswith('星期'):
return '星期几:{}'.format(result)
elif result.endswith('节'):
return '节日:{}'.format(result)
else:
return '今天是:{}'.format(result)
else:
return '其他'
这里我们在if/else
中又嵌套了一层判断逻辑,当然这只是一层简单的嵌套,这么写没有问题。而随着项目的演进,功能越来越复杂,如果我们需要在嵌套的逻辑中再加一层嵌套,或者更改这层嵌套逻辑。直接在原有的逻辑中改的话,不免要增大修改的代价和风险。更为重要的是,这对以后的维护和扩展增加了难度。
编辑复杂的项目时,为了使代码逻辑更清晰,更易读易于维护,我们需要对原有的if/else
中的嵌套做一个类的封装,封装一个判断的方法(judge()
)以及一个执行行为方法(action()
),它们分别封装了原代码中的if
判断和判断后执行的行为。
class TodayIsWeek(object):
def judge(self, result):
return result.startswith('星期')
def action(self, result):
# do something
class TodayIsFestival(object):
def judge(self, result):
return result.endswith('节')
def action(self, result):
# do something
class TodayIsOther(object):
def judge(self, result):
return not (result.startswith('星期') and result.endswith('节'))
def action(self, result):
# do something
对于上面的程序,这么封装肯定是多余的,而如果程序特别复杂,这样做不仅不会显得过度设计,还能让代码结构逻辑更加清晰。我们只需要将上面的封装放到一个表里,遍历它就可以了:
def get_today(today):
if today in days:
result = days.get(today)
# 遍历
for obj in [TodayIsWeek, TodayIsFestival, TodayIsOther]:
run = obj()
if run.judge(result): return run.action()
else:
return 'not in days'
最后
在python代码的编写中,我们应该尽量不写过多的逻辑判断嵌套,避免if/else
嵌套地狱。对于过于复杂的逻辑判断,尽量对他进行封装,使用表驱动法来分离数据和逻辑,保证可读性同时减少维护代码的成本。