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

如果在IT行业的时间够长的话,可能还记得大约10几年前,设计模式风靡一时的时候,有过一段反 "if" 的运动。

所谓的反"if"运动,其实是夸大了"if"语句带来的问题,比如当时提出的问题有:

  1. 代码不好维护,特别是if或者else中的代码比较多的时候
  2. ifelse if分支太多的时候,代码难以阅读和修改
  3. 阅读含有if的代码时,必须在自己的头脑中模拟执行,会消耗你的精神能量
  4. ... ... 等等

这些问题确实存在,但是因为这些就彻底禁止if的话,就过于极端,因噎废食了。

代码中分支和循环是不可避免的,完全禁止if之后,在某些时候会产生了更加复杂和令人发指的代码,

所以,最后这个反"if"的运动也不了了之,慢慢消亡了。

不过,为了反"if"而产生的一些替代方案,我挑了三个 还值得一看的方案,供大家参考参考。

其它还有很多方案都不太靠谱,就不一一赘述了。

1. 拆分成多个方法

这种重构"if"的方法是将每个分支单独封装成一个独立的方法。

比如:

python 复制代码
def select_model(is_regression=True):
    if is_regression:
        print("选择【回归】模型")
    else:
        print("选择【分类】模型")

# 测试代码
select_model(True)
select_model(False)

# 运行结果
选择【回归】模型
选择【分类】模型

示例中,方法select_model通过is_regression参数来决定调用哪种模型。

重构之后:

python 复制代码
def select_regression():
        print("选择【回归】模型")

def select_classifier():
        print("选择【分类】模型")

# 测试代码
select_regression()
select_classifier()

# 运行结果
选择【回归】模型
选择【分类】模型

将原方法拆分为两个新方法,"if"就消失了。

2. 改成多态

如果一个函数中分支比较多,比如:

python 复制代码
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("无法识别动物:{}".format(animal))

# 测试代码
cry("dog")
cry("cat")
cry("sheep")
cry("cow")

# 运行结果
dog :汪汪~
cat :喵喵~
sheep :咩咩~
cow :哞哞~

cry函数根据不同的参数来判断输出内容,

如果分支多了,并且每个分支中的代码也比较多的时候,会比较难于维护。

对于上面的"if"分支较多的情况,可以用多态的方式来改造。

也就是,封装一个抽象类,其中包含抽象方法cry,然后不同的动物继承抽象类实现自己的cry方法。

python 复制代码
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))

# 测试代码
animal = Dog()
animal.cry()

animal = Cat()
animal.cry()

animal = Sheep()
animal.cry()

animal = Cow()
animal.cry()

# 运行结果
dog :汪汪~
cat :喵喵~
sheep :咩咩~
cow :哞哞~

3. 将条件判断内联

对于比较复杂的条件判断,可以用内联的方式的来改善。

比如,下面构造一个略微复杂的判断:

python 复制代码
def complex_judge(foo, bar, baz):
    if foo:
        if bar:
            return True

    if baz:
        return True
    else:
        return False

# 测试代码
print(complex_judge(True, True, False))
print(complex_judge(True, False, False))
print(complex_judge(False, True, True))

# 运行结果
True
False
True

这样写不仅阅读比较困难,增加或修改判断条件时也很麻烦。

用内联的方式(也就是用 andor)修改后,简洁很多。

python 复制代码
def complex_judge(foo, bar, baz):
    return foo and bar or baz

# 测试代码
print(complex_judge(True, True, False))
print(complex_judge(True, False, False))
print(complex_judge(False, True, True))

# 运行结果
True
False
True

4. 总结

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

相关推荐
程序员榴莲21 小时前
Python 中的 @property:像访问属性一样调用方法
开发语言·前端·python
坐吃山猪21 小时前
【Nanobot】README04_LEVEL2 提供商系统设计
python·源码·agent·nanobot
坐吃山猪21 小时前
【Nanobot】README09_LEVEL4 添加新聊天渠道
开发语言·网络·python·源码·nanobot
Mr.朱鹏21 小时前
9-检索增强生成RAG详解
python·gpt·langchain·大模型·llm·rag
shehuiyuelaiyuehao21 小时前
算法27,二维前缀和
开发语言·python·算法
码界筑梦坊21 小时前
125-基于Flask的客户购物偏好数据可视化分析系统
python·信息可视化·flask·毕业设计
测试秃头怪1 天前
接口测试与常用接口测试工具详解
自动化测试·软件测试·python·测试工具·职场和发展·测试用例·接口测试
坐吃山猪1 天前
【Nanobot】README03_LEVEL2_工具系统架构
python·源码·agent·nanobot
河阿里1 天前
Python容器:特性、区别和使用场景
开发语言·python
AC赳赳老秦1 天前
OpenClaw与思维导图工具联动:自动生成工作规划脑图、拆解任务节点,适配职场管理
java·大数据·服务器·数据库·python·php·openclaw