三元表达式很多时候,使用普通if/else语句的代码可读性确实更好。一味追求三元表达式很容易诱使你写出复杂且可读性差的代码。所以,记住只用三元表达式处理简单的逻辑分支。例如,下面的代码适合使用三元表达式:language="python"ifyou.favor("dynamic")else"golang"对于大多数情况,使用普通的if/else语句。例如,下面的代码self.enabled=Trueifkwargs['enable']andkwargs['already_started']=='Yes'andself.checked==1elseFalseself.need_use_ssl=Trueifkwargs['use_ssl']isTrueelseFalseifkwargs['allow_insecure']isFalseelseTrue以上两种情况,三元表达式的使用使得代码很长,而且第二行有条件嵌套,代码更难理解。后面的章节会介绍简化的if-else语句的具体技巧,这里要记住三元表达式需要慎用。重构if...else语句嵌套的if-else地狱如果您真的很欣赏这种代码并且内心有一种想弄清楚它在做什么的冲动,请跳过本章。简化函数defget_payment_amount(account:Account)->float:result=0.0ifaccount.is_deactivated:result=get_deactivated_amount(account)else:ifaccount.is_separated:result=get_separated_amount(account)else:ifaccount.is_retired:result=get_retired_amount(account)else:result=get_normal_amount(account)returnresult这段代码段有很多条件嵌套,用魏语简化这段代码段,也叫提前结束(earlyending)defget_payment_amount(account:Account)->float:ifaccount.is_deactivated:returnget_deactivated_amount(account)ifaccount.is_separated:returnget_separated_amount(account)ifaccount.is_retired:returnget_retired_amount(account)returnget_normal_amount(account)重构之后,基本上去掉了所有else语句,使得整个功能更清晰,更容易理解。使用多态替代条件表达式下面的代码片段是判断员工是否符合休假条件的代码defis_eligible_for_pto(employee:Employee)->bool:ifemployee.type=="Manager":returnemployee.hired_days>100andemployee.performance>=0.8elifemployee.type=="Developer":returnemployee.hired_days>30andemployee.performance>=0.6andemployee.is_on_dutyisFalseelifemployee.type=="Intern":返回employee.hired_days>7andemployee.performance>=0.4andemployee.is_on_dutyisFalseelifemployee.type=="Director":returnemployee.is_on_dutyisFalsereturnFalse我们重构了用守卫语言替换条件分支,但是代码看起来还是这样的非常繁琐,因为每个条件分支都有很长很复杂的判断逻辑,而且对于这个功能来说,需要太多的知识。必须知道employee对象的属性和影响PTO的相关条件才能判断。.如果我们用多态来重构这段代码,就可以把判断逻辑封装在具体的子类中,只需要在函数中调用相应的接口,而不用再去了解Employee对象,就可以搞定了。员工类:类型:strhired_days:intperformance:float@propertydefpto_condition(self)->bool:returnFalseclassManager(Employee):@propertydefpto_condition(self)->bool:returnself.hired_days>100and\self.performance>=0.8classDeveloper(Employee):@propertydefpto_condition(self)->bool:returnself.hired_days>30and\self.performance>=0.6and\self.is_on_dutyisFalseclassIntern(Employee):@propertydefpto_condition(self)->bool:returnself.hired_days>7and\self.performance>=0.4and\self.is_on_dutyisFalseclass主管(员工):@propertydefpto_condition(self)->bool:returnself.is_on_dutyisFalsedefis_eligible_for_pto(employee:Employee)->bool:returnemployee.pto_conditionisTrue用否判断断代替代else分支bad:def_to_list(src):ifsrc:returnsrcifisinstance(src,list)else[src]else:return[]good:def_to_list(src):ifnotsrc:return[]returnsrcifisinstance(src,list)else[src]逻辑重构使用for...else而不是flag来简化代码bad:flag=Falseforindexinrange(10):ifindex==20:flag=Truebreakifnotflag:print("notfoundit")good:forindexinrange(10):ifindex=20:breakelse:print("notfoundit")用字典代替条件判断Python中没有switch语句(新版本才支持),所以当有很多条件分支,写一个很长的if判断语句,比如下面这样:='event_3':returncall_event_handler_3()else:raiseUnknownEventError这种代码不仅有多个条件分支,而且看起来比较复杂,而且还是manife重码站。我们可以使用Python的dict来重做这个条件分支的代码结构,减少条件分支,去除重复代码。defglobal_events_dispatcher(事件):event_handlers={'event_1':call_event_handler_1,'event_2':call_event_handler_2,'event_3':call_event_handler_3,}ifevent_handlers.get(event,None):func=event_handlers(event)returnfunc()raiseUnknownEventError重构后代码只有一条条件判断语句,函数的行为没有改变,使得整个函数的逻辑更容易理解。补充关于如何重构条件分支语句,可以阅读第10章:简化条件逻辑,其中列举了多种简化条件逻辑的常用重构技巧,并附有大量实例,推荐阅读。
