三元表达式
在很多状况下,应用一般的 if/else
语句的代码可读性的确更好。自觉谋求三元表达式很容易引诱你写出简单、可读性差的代码。
所以,请记得只用三元表达式解决简略的逻辑分支。比方如下代码是适宜应用三元表达式的:
language = "python" if you.favor("dynamic") else "golang"
对于绝大多数状况,还是应用一般的 if/else
语句吧。比方上面代码
self.enabled = True if kwargs['enable'] and kwargs['already_started'] == 'Yes' and self.checked == 1 else False
self.need_use_ssl = True if kwargs['use_ssl'] is True else False if kwargs['allow_insecure'] is False else True
下面两种状况应用三元表达式反而将代码写的很长,第二行还有条件嵌套,使代码更加不容易了解
上面章节会介绍简化 if-else
statement 的具体技巧,这里咱们记住 三元表达式须要慎用。
重构 if…else 语句
Nested if-else hell
如果你对这种代码十分观赏,并且心田有一种想要搞清楚它在干什么的激动,请略过这章的内容。
应用卫语语句简化函数
def get_payment_amount(account: Account) -> float:
result = 0.0
if account.is_deactivated:
result = get_deacticated_amount(account)
else:
if account.is_separated:
result = get_separated_amount(account)
else:
if account.is_retired:
result = get_retired_amount(account)
else:
result = get_normal_amount(account)
return result
该代码段存在大量的条件嵌套,应用卫语简化这个代码段,也叫提前结束(early ending)
def get_payment_amount(account: Account) -> float:
if account.is_deactivated:
return get_deacticated_amount(account)
if account.is_separated:
return get_separated_amount(account)
if account.is_retired:
return get_retired_amount(account)
return get_normal_amount(account)
重构后,根本移除了所有的 else 语句,使整个函数变得更加清晰,容易了解。
应用多态代替条件表达式
以下代码段是判断一个员工是否可能休假的代码
def is_eligible_for_pto(employee: Employee) -> bool:
if employee.type == "Manager":
return employee.hired_days > 100 and employee.performance >= 0.8
elif employee.type == "Developer":
return employee.hired_days > 30 and employee.performance >= 0.6 and employee.is_on_duty is False
elif employee.type == "Intern":
return employee.hired_days > 7 and employee.performance >= 0.4 and employee.is_on_duty is False
elif employee.type == "Director":
return employee.is_on_duty is False
return False
咱们曾经用卫语代替条件分支的办法重构过了,然而这个代码仍然看起来很繁琐,因为每个条件分支都有很长很简单的判断逻辑,而对于这个函数来说,它须要的常识太多了,必须晓得 employee 这个对象的属性,以及影响 PTO 的相干条件能力判断进去。
咱们如果应用多态的形式来重构这段代码,可能将判断逻辑封装在具体的子类中,并且只须要在函数中调用相应接口即可,并不需要晓得对于 Employee 这个对象更多的信息即可实现工作。
class Employee:
type: str
hired_days: int
performance: float
@property
def pto_condition(self) -> bool:
return False
class Manager(Employee):
@property
def pto_condition(self) -> bool:
return self.hired_days > 100 and \
self.performance >= 0.8
class Developer(Employee):
@property
def pto_condition(self) -> bool:
return self.hired_days > 30 and \
self.performance >= 0.6 and \
self.is_on_duty is False
class Intern(Employee):
@property
def pto_condition(self) -> bool:
return self.hired_days > 7 and \
self.performance >= 0.4 and \
self.is_on_duty is False
class Director(Employee):
@property
def pto_condition(self) -> bool:
return self.is_on_duty is False
def is_eligible_for_pto(employee: Employee) -> bool:
return employee.pto_condition is True
用否定条件判断代替 else 分支
bad:
def _to_list(src):
if src:
return src if isinstance(src, list) else [src]
else:
return []
good:
def _to_list(src):
if not src:
return []
return src if isinstance(src, list) else [src]
逻辑重构
应用 for...else
代替 flag 以简化代码
bad:
flag = False
for index in range(10):
if index == 20:
flag = True
break
if not flag:
print("not found it")
good:
for index in range(10):
if index = 20:
break
else:
print("not found it")
应用字典代替条件判断
Python 中是不存在 switch 语句的,(新版本才反对),所以,当存在较多条件分支时,会写十分长的 if
判断语句,比方像上面这种:
def global_events_dispatcher(event):
if event == 'event_1':
return call_event_handler_1()
elif event == 'event_2':
return call_event_handler_2()
elif event == 'event_3':
return call_event_handler_3()
else:
raise UnknownEventError
这种代码岂但有多个条件分支,看起来比较复杂,同时也是反复代码的一种体现。
咱们能够利用 Python 的dict
对这段条件分支代码进行重构,缩小条件分支,去除反复代码。
def global_events_dispatcher(event):
event_handlers = {
'event_1': call_event_handler_1,
'event_2': call_event_handler_2,
'event_3': call_event_handler_3,
}
if event_handlers.get(event, None):
func = event_handlers(event)
return func()
raise UnknownEventError
重构后代码只有一个条件判断语句,函数的行为没有产生任何变动,让整个函数的逻辑变得更加容易了解。
补充
对于如何重构条件分支语句,能够延长浏览《重构:改善既有代码的设计(第 2 版)》第 10 章:简化条件逻辑,外面列举了多种常见的简化条件逻辑的重构手法,并配有大量的例子,举荐浏览。