找回密码
 立即注册
首页 业界区 业界 写代码不用"if"行不行,曾经的反 if 运动 ...

写代码不用"if"行不行,曾经的反 if 运动

璋锌 昨天 08:24
如果在IT行业的时间够长的话,可能还记得大约10几年前,设计模式风靡一时的时候,有过一段反 "if" 的运动。
所谓的反"if"运动,其实是夸大了"if"语句带来的问题,比如当时提出的问题有:

  • 代码不好维护,特别是if或者else中的代码比较多的时候
  • if和 else if分支太多的时候,代码难以阅读和修改
  • 阅读含有if的代码时,必须在自己的头脑中模拟执行,会消耗你的精神能量
  • ... ... 等等
这些问题确实存在,但是因为这些就彻底禁止if的话,就过于极端,因噎废食了。
代码中分支和循环是不可避免的,完全禁止if之后,在某些时候会产生了更加复杂和令人发指的代码,
所以,最后这个反"if"的运动也不了了之,慢慢消亡了。
不过,为了反"if"而产生的一些替代方案,我挑了三个还值得一看的方案,供大家参考参考。
其它还有很多方案都不太靠谱,就不一一赘述了。
1. 拆分成多个方法

这种重构"if"的方法是将每个分支单独封装成一个独立的方法。
比如:
  1. def select_model(is_regression=True):
  2.     if is_regression:
  3.         print("选择【回归】模型")
  4.     else:
  5.         print("选择【分类】模型")
  6. # 测试代码
  7. select_model(True)
  8. select_model(False)
  9. # 运行结果
  10. 选择【回归】模型
  11. 选择【分类】模型
复制代码
示例中,方法select_model通过is_regression参数来决定调用哪种模型。
重构之后:
  1. def select_regression():
  2.         print("选择【回归】模型")
  3. def select_classifier():
  4.         print("选择【分类】模型")
  5. # 测试代码
  6. select_regression()
  7. select_classifier()
  8. # 运行结果
  9. 选择【回归】模型
  10. 选择【分类】模型
复制代码
将原方法拆分为两个新方法,"if"就消失了。
2. 改成多态

如果一个函数中分支比较多,比如:
  1. def cry(animal):
  2.     if animal == "dog":
  3.         print("{} :汪汪~".format(animal))
  4.     elif animal == "cat":
  5.         print("{} :喵喵~".format(animal))
  6.     elif animal == "sheep":
  7.         print("{} :咩咩~".format(animal))
  8.     elif animal == "cow":
  9.         print("{} :哞哞~".format(animal))
  10.     else:
  11.         print("无法识别动物:{}".format(animal))
  12. # 测试代码
  13. cry("dog")
  14. cry("cat")
  15. cry("sheep")
  16. cry("cow")
  17. # 运行结果
  18. dog :汪汪~
  19. cat :喵喵~
  20. sheep :咩咩~
  21. cow :哞哞~
复制代码
cry函数根据不同的参数来判断输出内容,
如果分支多了,并且每个分支中的代码也比较多的时候,会比较难于维护。
对于上面的"if"分支较多的情况,可以用多态的方式来改造。
也就是,封装一个抽象类,其中包含抽象方法cry,然后不同的动物继承抽象类实现自己的cry方法。
  1. from abc import ABCMeta, abstractclassmethod
  2. class Animal(metaclass=ABCMeta):
  3.     def __init__(self, name) -> None:
  4.         self.name = name
  5.     @abstractclassmethod
  6.     def cry(self):
  7.         pass
  8. class Dog(Animal):
  9.     def __init__(self) -> None:
  10.         super().__init__("dog")
  11.     def cry(self):
  12.         print("{} :汪汪~".format(self.name))
  13. class Cat(Animal):
  14.     def __init__(self) -> None:
  15.         super().__init__("cat")
  16.     def cry(self):
  17.         print("{} :喵喵~".format(self.name))
  18. class Sheep(Animal):
  19.     def __init__(self) -> None:
  20.         super().__init__("sheep")
  21.     def cry(self):
  22.         print("{} :咩咩~".format(self.name))
  23. class Cow(Animal):
  24.     def __init__(self) -> None:
  25.         super().__init__("cow")
  26.     def cry(self):
  27.         print("{} :哞哞~".format(self.name))
  28. # 测试代码
  29. animal = Dog()
  30. animal.cry()
  31. animal = Cat()
  32. animal.cry()
  33. animal = Sheep()
  34. animal.cry()
  35. animal = Cow()
  36. animal.cry()
  37. # 运行结果
  38. dog :汪汪~
  39. cat :喵喵~
  40. sheep :咩咩~
  41. cow :哞哞~
复制代码
3. 将条件判断内联

对于比较复杂的条件判断,可以用内联的方式的来改善。
比如,下面构造一个略微复杂的判断:
  1. def complex_judge(foo, bar, baz):
  2.     if foo:
  3.         if bar:
  4.             return True
  5.     if baz:
  6.         return True
  7.     else:
  8.         return False
  9. # 测试代码
  10. print(complex_judge(True, True, False))
  11. print(complex_judge(True, False, False))
  12. print(complex_judge(False, True, True))
  13. # 运行结果
  14. True
  15. False
  16. True
复制代码
这样写不仅阅读比较困难,增加或修改判断条件时也很麻烦。
用内联的方式(也就是用 and 和 or)修改后,简洁很多。
  1. def complex_judge(foo, bar, baz):
  2.     return foo and bar or baz
  3. # 测试代码
  4. print(complex_judge(True, True, False))
  5. print(complex_judge(True, False, False))
  6. print(complex_judge(False, True, True))
  7. # 运行结果
  8. True
  9. False
  10. True
复制代码
4. 总结

反"if"运动早已结束,对"if"彻底抛弃显得很荒谬,但也不能对此全盘否定。
"if"语句会影响阅读代码时流畅的思路,对代码中"if"的使用保持慎重的态度还是很有必要的。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册