写代码不用"if"行不行,曾经的反 if 运动
如果在IT行业的时间够长的话,可能还记得大约10几年前,设计模式风靡一时的时候,有过一段反 "if" 的运动。
所谓的反"if"运动,其实是夸大了"if"语句带来的问题,比如当时提出的问题有:
- 代码不好维护,特别是
if或者else中的代码比较多的时候 if和else if分支太多的时候,代码难以阅读和修改- 阅读含有
if的代码时,必须在自己的头脑中模拟执行,会消耗你的精神能量 - ... ... 等等
这些问题确实存在,但是因为这些就彻底禁止if的话,就过于极端,因噎废食了。
代码中分支和循环是不可避免的,完全禁止if之后,在某些时候会产生了更加复杂和令人发指的代码,
所以,最后这个反"if"的运动也不了了之,慢慢消亡了。
不过,为了反"if"而产生的一些替代方案,我挑了三个还值得一看的方案,供大家参考参考。
其它还有很多方案都不太靠谱,就不一一赘述了。
1. 拆分成多个方法
这种重构"if"的方法是将每个分支单独封装成一个独立的方法。
比如:
def select_model(is_regression=True):
if is_regression:
print("选择【回归】模型")
else:
print("选择【分类】模型")
# 测试代码
select_model(True)
select_model(False)
# 运行结果
选择【回归】模型
选择【分类】模型
示例中,方法select_model通过is_regression参数来决定调用哪种模型。
重构之后:
def select_regression():
print("选择【回归】模型")
def select_classifier():
print("选择【分类】模型")
# 测试代码
select_regression()
select_classifier()
# 运行结果
选择【回归】模型
选择【分类】模型
将原方法拆分为两个新方法,"if"就消失了。
2. 改成多态
如果一个函数中分支比较多,比如:
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方法。
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. 将条件判断内联
对于比较复杂的条件判断,可以用内联的方式的来改善。
比如,下面构造一个略微复杂的判断:
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
这样写不仅阅读比较困难,增加或修改判断条件时也很麻烦。
用内联的方式(也就是用 and 和 or)修改后,简洁很多。
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"的使用保持慎重的态度还是很有必要的。
写代码不用"if"行不行,曾经的反 if 运动的更多相关文章
- 【Unity 框架】 QFramework v1.0 使用指南 工具篇: 16. LiveCodingKit 写代码不用停止运行的利器 | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏
我们在用 Unity 开发的时候,每次编写或修改一点代码就需要进行 停止运行->编写代码->等待编译->运行游戏. 而在很多情况下这个过程是一个比较耗神的过程,因为开发者需要等待,还 ...
- (转)如何基于FFMPEG和SDL写一个少于1000行代码的视频播放器
原文地址:http://www.dranger.com/ffmpeg/ FFMPEG是一个很好的库,可以用来创建视频应用或者生成特定的工具.FFMPEG几乎为你把所有的繁重工作都做了,比如解码.编码. ...
- [翻译] Canvas 不用写代码的动画
Canvas 不用写代码的动画 https://github.com/CanvasPod/Canvas Canvas is a project to simplify iOS development ...
- 【优雅代码】04-1行代码完成多线程,别再写runnable了
[优雅代码]04-1行代码完成多线程,别再写runnable了 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮 ...
- 在linux上一行代码不用写实现自动采集+hadoop分词
在linux上一行代码不用写实现自动采集+hadoop分词 将下面的shell脚本保存成到xxx.sh,然后执行即可 cd /opt/hadoop mkdir spider wget -O spide ...
- Notepad2(C语言+Windows消息写的,24592行代码)
C语言+Windows消息写的,24592行代码 http://www.flos-freeware.ch/
- 用Python写一个随机数字生成代码,5行代码超简单
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 第一步,安装 random 库 random库是使用随机数的Python标准库 ...
- 使用 .NET WinForm 开发所见即所得的 IDE 开发环境,实现不写代码直接生成应用程序
直接切入正题,这是我09年到11年左右业余时间编写的项目,最初的想法很简单,做一个能拖拖拽拽就直接生成应用程序的工具,不用写代码,把能想到的业务操作全部封装起来,通过配置的方式把这些业务操作组织起来运 ...
- 王炸!!IDEA 2021.1 推出语音、视频功能,边写代码边聊天,我真的服了…
IDEA 2020.3 刚没用多久,2021.1 又陆续给我推送更新了: 启动就提醒更新,麻烦,那不如更新下,体验下新版本. 如上图所示,2021.1 更新了 9 个新特性,下面栈长会一一体验给大家介 ...
- ClownFish:比手写代码还快的通用数据访问层
http://www.cnblogs.com/fish-li/archive/2012/07/17/ClownFish.html 阅读目录 开始 ClownFish是什么? 比手写代码还快的执行速度 ...
随机推荐
- 从0开始,Cloudreve开源云盘在centos7上部署,并可在外网访问(资料整合)
全程我在网络上收集这些资料,太零碎了,每一个一看就会,一动手就废,而且很多都不能实现我白嫖的梦想 我一个人折腾了快一周,现在可以正常访问手机电脑多端访问 给个赞再走吧 此处为没有公网IP(回去折腾你家 ...
- SpringBoot 测试实践 - 3:@MockBean、@SpyBean 、提升测试运行速度、Testcontainer
编写测试的时候,我们必须保证外部依赖行为一致,也需要模拟一些边界条件,所以我们需要使用 Mock 来模拟对象的行为.SpringBoot 提供了 @MockBean 和 @SpyBean 注解,可以方 ...
- Flutter系列文章-Flutter应用优化
当涉及到优化 Flutter 应用时,考虑性能.UI 渲染和内存管理是至关重要的.在本篇文章中,我们将通过实例深入讨论这些主题,展示如何通过优化技巧改进你的 Flutter 应用. 代码性能优化 1. ...
- Midjourney的一些学习心得:如何高效的图生图
注意本文没有什么长篇大论,全部是自己的学习心得. 心得体会:如何图生图 今天在一篇midjourney看到好图应该怎么抄. 相信经常会看到好图也想要的,但是要么抄不出感觉,要么抄过来把水印也抄了,这一 ...
- 文心一言 VS 讯飞星火 VS chatgpt (82)-- 算法导论8.1 1题
一.如果用go语言,在一棵比较排序算法的决策树中,一个叶结点可能的最小深度是多少? 文心一言: 在一个排序决策树(如二叉搜索树)中,每个叶节点的最小深度等于输入数据中最大元素与最小元素之间的位距离.这 ...
- 应用程序接口(API)安全的入门指南
什么是 API? 对于初学者来说,API 是指为两个不同的应用之间实现流畅通信,而设计的应用程序编程接口.它通常被称为应用程序的"中间人".由于我们需要保护用户的持有数据. ...
- ios添加库文件
- HTML一键打包APK工具最新版1.9.1更新(附下载地址)
HMTL网址打包APK,可以把本地HTML项目, Egret游戏,网页游戏,或者网站打包为一个安卓应用APK文件,无需编写任何代码,也无需配置安卓开发环境,支持在最新的安卓设备上安装运行. HTML一 ...
- UM 百度富文本编辑器上传报错
看下报错信息 这三张图记录了当时,上传图片 遇见的报错信息 最终解决方案 我把UM下jsp文件下的ueditor-mini.jar包拷贝到WEB_INF下的lib文件夹下,就成功了. maven的话把 ...
- 多主架构:VLDB技术论文《Taurus MM: bringing multi-master to the cloud》解读
本文分享自华为云社区<多主创新,让云数据库性能更卓越>,作者: GaussDB 数据库. 华为<Taurus MM: bringing multi-master to the clo ...