当前位置: 首页 > 后端技术 > Python

我通过这个操作来提高代码的可读性上一个台阶

时间:2023-03-26 18:42:33 Python

背景假设有一个课程学习管理系统,其中有一个名为status的表字段,用来标记某门课程学生的学习状态,它在数据库中的类型是int。现在我们的业务系统里面充斥着很多status==xxx:ifstatus==0:passelifstatus==1:pass...iffinished:status=2这样的代码相信你能看出问题所在,如For一个刚接手项目的人,肯定会疑惑这里的0、1、2、3的值代表什么。你必须去代码中找出状态是如何定义的,有哪些值,它们是什么意思?如果文档中没有写清楚这些值的含义,那你就得先找到写代码的人(你心里肯定会骂是哪个傻子写的),所以这段代码最大的问题是它的可读性差。就连作者自己也不能说过段时间再看就不会糊涂了。重构那么我们如何重构这段代码以提高可读性呢?,有几种重构方案,接下来我将列出这些方法。第一种:使用枚举枚举(Enum)是Python自带的特性,定义多个有限值是绝对必要的。最佳应用场景。先定义状态枚举类importenumclassStudyStatusEnum(enum.Enum):no_start=0#未开始学习=1#学习结束=2#学习结束expired=3#expired然后修改之前的逻辑为:ifstatus==StudyStatusEnum.no_start:passelifstatus==StudyStatusEnum.leanring:passiffinished:status=StudyStatusEnum.finish如果你系统中使用的ORM框架是SQLAlchemy,还必须修改status属性classStudy(Models)的定义:#status=db.Column(db.SmallInteger,default=0,comment="StudyStatus0NotStarted1Learning2Completed")status=db.Column(Enum(StudyStatusEnum),default=StudyStatusEnum.no_start)这个修改其实有第一个问题是那枚举类型对应的是数据库中的string类型,但实际上我们要存储的是一个int类型,它对应的是枚举的value值,而不是枚举的name属性。所以,这时候我们可以根据SQLAlchemy提供的TypeDecorator,自定义一个名为IntEnum的Enum类型。fromsqlalchemyimportTypeDecorator,IntegerclassIntEnum(TypeDecorator):"""Integer枚举类型主要用于state等场景"""impl=Integerdef__init__(self,enumtype,*args,**kwargs):super()。__init__(*args,**kwargs)self._enumtype=enumtypedefprocess_bind_param(self,value,dialect):#入库时调用该方法,返回枚举的值returnvalue.valuedefprocess_result_value(self,value,dialect):#当值从数据库加载到内存时,返回一个枚举实例returnself._enumtype(value)我们只需要重写这三个方法就可以实现一个可以保存int类型的枚举。status=db.Column(IntEnum(StudyStatusEnum),default=StudyStatusEnum.no_start)类型2:使用常量,将status所有可能的值直接替换为常量值NO_FINISH=0LEARNING=1FINISH=2EXPRIED=3ifstatus==NO_FINISH:passelifstatus==LEARNING:passiffinished:status=FINISH也可以提高可读性,但是有个问题就是如果这样的字段很多,不仅是学习状态,还有考试状态,如果每个状态都有几个值,然后我们将定义许多类似的常量值。其实这四个值应该归为一类,就是学习状态,那么我们能不能把它们归为一类呢?答案是使用namedtuple。第三种方法:使用namedtuple。namedtuple是命名元组,即具有名称的元组。元组中的每个元素对应一个名称。是不是很适合这种场景?而且它比用类和枚举来表示它更轻量。从集合导入namedtupleStudyStatus=namedtuple("StudyStatus","no_start,learning,finish,end")STUDY_STATUS=StudyStatus(0,1,2,3)ifstatus==STUDY_STATUS.no_start:passelifstatus==STUDY_STATUS.learning:passiffinished:status=STUDY_STATUS.finish这样我们只需要定义一个枚举常量对象,它包含4个值,代表4种不同的状态。namedtuple可以被认为是一个只有属性没有方法的更轻量级的类。使用namedtuple进行重构,不需要在Model层面修改字段属性。变化很小,但可读性大大提高。以上就是一个使用namedtuple提高代码可读性的实际案例。看看你的代码中是否充满了这样的代码,并尝试重构它。最近为初学者整理了数百G的Python学习资料,包括电子书、教程、源码等,免费分享给大家!想上“Python编程学习圈”,发“J”免费领取