写代码不用"if"行不行,曾经的反 if 运动
如果在IT行業(yè)的時(shí)間夠長(zhǎng)的話,可能還記得大約10幾年前,設(shè)計(jì)模式風(fēng)靡一時(shí)的時(shí)候,有過一段反 "if" 的運(yùn)動(dòng)。
所謂的反"if"運(yùn)動(dòng),其實(shí)是夸大了"if"語(yǔ)句帶來(lái)的問題,比如當(dāng)時(shí)提出的問題有:
- 代碼不好維護(hù),特別是
if或者else中的代碼比較多的時(shí)候 -
if和else if分支太多的時(shí)候,代碼難以閱讀和修改 - 閱讀含有
if的代碼時(shí),必須在自己的頭腦中模擬執(zhí)行,會(huì)消耗你的精神能量 - ... ... 等等
這些問題確實(shí)存在,但是因?yàn)檫@些就徹底禁止if的話,就過于極端,因噎廢食了。
代碼中分支和循環(huán)是不可避免的,完全禁止if之后,在某些時(shí)候會(huì)產(chǎn)生了更加復(fù)雜和令人發(fā)指的代碼,
所以,最后這個(gè)反"if"的運(yùn)動(dòng)也不了了之,慢慢消亡了。
不過,為了反"if"而產(chǎn)生的一些替代方案,我挑了三個(gè)還值得一看的方案,供大家參考參考。
其它還有很多方案都不太靠譜,就不一一贅述了。
1. 拆分成多個(gè)方法
這種重構(gòu)"if"的方法是將每個(gè)分支單獨(dú)封裝成一個(gè)獨(dú)立的方法。
比如:
def select_model(is_regression=True):
if is_regression:
print("選擇【回歸】模型")
else:
print("選擇【分類】模型")
# 測(cè)試代碼
select_model(True)
select_model(False)
# 運(yùn)行結(jié)果
選擇【回歸】模型
選擇【分類】模型
示例中,方法select_model通過is_regression參數(shù)來(lái)決定調(diào)用哪種模型。
重構(gòu)之后:
def select_regression():
print("選擇【回歸】模型")
def select_classifier():
print("選擇【分類】模型")
# 測(cè)試代碼
select_regression()
select_classifier()
# 運(yùn)行結(jié)果
選擇【回歸】模型
選擇【分類】模型
將原方法拆分為兩個(gè)新方法,"if"就消失了。
2. 改成多態(tài)
如果一個(gè)函數(shù)中分支比較多,比如:
def cry(animal):
if animal == "dog":
print("{} :汪汪~".format(animal))
elif animal == "cat":
print("{} :喵喵~".format(animal))
elif animal == "sheep":
print("{} :咩咩~".format(animal))
elif animal == "cow":
print("{} :哞哞~".format(animal))
else:
print("無(wú)法識(shí)別動(dòng)物:{}".format(animal))
# 測(cè)試代碼
cry("dog")
cry("cat")
cry("sheep")
cry("cow")
# 運(yùn)行結(jié)果
dog :汪汪~
cat :喵喵~
sheep :咩咩~
cow :哞哞~
cry函數(shù)根據(jù)不同的參數(shù)來(lái)判斷輸出內(nèi)容,
如果分支多了,并且每個(gè)分支中的代碼也比較多的時(shí)候,會(huì)比較難于維護(hù)。
對(duì)于上面的"if"分支較多的情況,可以用多態(tài)的方式來(lái)改造。
也就是,封裝一個(gè)抽象類,其中包含抽象方法cry,然后不同的動(dòng)物繼承抽象類實(shí)現(xiàn)自己的cry方法。
from abc import ABCMeta, abstractclassmethod
class Animal(metaclass=ABCMeta):
def __init__(self, name) -> None:
self.name = name
@abstractclassmethod
def cry(self):
pass
class Dog(Animal):
def __init__(self) -> None:
super().__init__("dog")
def cry(self):
print("{} :汪汪~".format(self.name))
class Cat(Animal):
def __init__(self) -> None:
super().__init__("cat")
def cry(self):
print("{} :喵喵~".format(self.name))
class Sheep(Animal):
def __init__(self) -> None:
super().__init__("sheep")
def cry(self):
print("{} :咩咩~".format(self.name))
class Cow(Animal):
def __init__(self) -> None:
super().__init__("cow")
def cry(self):
print("{} :哞哞~".format(self.name))
# 測(cè)試代碼
animal = Dog()
animal.cry()
animal = Cat()
animal.cry()
animal = Sheep()
animal.cry()
animal = Cow()
animal.cry()
# 運(yùn)行結(jié)果
dog :汪汪~
cat :喵喵~
sheep :咩咩~
cow :哞哞~
3. 將條件判斷內(nèi)聯(lián)
對(duì)于比較復(fù)雜的條件判斷,可以用內(nèi)聯(lián)的方式的來(lái)改善。
比如,下面構(gòu)造一個(gè)略微復(fù)雜的判斷:
def complex_judge(foo, bar, baz):
if foo:
if bar:
return True
if baz:
return True
else:
return False
# 測(cè)試代碼
print(complex_judge(True, True, False))
print(complex_judge(True, False, False))
print(complex_judge(False, True, True))
# 運(yùn)行結(jié)果
True
False
True
這樣寫不僅閱讀比較困難,增加或修改判斷條件時(shí)也很麻煩。
用內(nèi)聯(lián)的方式(也就是用 and 和 or)修改后,簡(jiǎn)潔很多。
def complex_judge(foo, bar, baz):
return foo and bar or baz
# 測(cè)試代碼
print(complex_judge(True, True, False))
print(complex_judge(True, False, False))
print(complex_judge(False, True, True))
# 運(yùn)行結(jié)果
True
False
True
4. 總結(jié)
反"if"運(yùn)動(dòng)早已結(jié)束,對(duì)"if"徹底拋棄顯得很荒謬,但也不能對(duì)此全盤否定。"if"語(yǔ)句會(huì)影響閱讀代碼時(shí)流暢的思路,對(duì)代碼中"if"的使用保持慎重的態(tài)度還是很有必要的。
總結(jié)
以上是生活随笔為你收集整理的写代码不用"if"行不行,曾经的反 if 运动的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flask 使用Jinja2模板引擎
- 下一篇: java读取照片Exif信息到实体类