<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          我用這個(gè)操作,代碼可讀性提升一個(gè)檔次

          共 3956字,需瀏覽 8分鐘

           ·

          2022-08-11 21:32



          ↑ 關(guān)注 + 星標(biāo) ,每天學(xué)Python新技能

          后臺(tái)回復(fù)【大禮包】送你Python自學(xué)大禮包


          背景

          假設(shè)有一個(gè)課程學(xué)習(xí)管理系統(tǒng),其中有個(gè)表的字段叫status,用來(lái)標(biāo)記學(xué)員某個(gè)課程的學(xué)習(xí)狀態(tài), 它在數(shù)據(jù)庫(kù)中的類型是int。

          現(xiàn)在我們的業(yè)務(wù)系統(tǒng)中充斥著大量諸如status==xxx這樣的代碼:

          if status==0:
              pass



          elif status==1:
              pass



          ...



          if  finished:
              status =2

          問(wèn)題

          相信你看到問(wèn)題所在了,作為一個(gè)剛接手項(xiàng)目的人來(lái)說(shuō),你肯定會(huì)疑惑這里的0、1、2、3這些值到底代表什么狀態(tài),你不得不去代碼中查找status是怎么定義的,有哪些值,分別代表什么意思?

          如果文檔中沒有寫清楚這些值對(duì)應(yīng)的含義,那你還要去找最開始寫這個(gè)代碼的人(內(nèi)心你肯定會(huì)罵這是哪個(gè)傻瓜寫的)

          所以這段代碼最大的問(wèn)題就是可讀性差,甚至即使作者自己也難說(shuō)隔一段時(shí)間再來(lái)看不會(huì)懵逼。

          重構(gòu)

          那么我們?nèi)绾蝸?lái)重構(gòu)這段代碼來(lái)提升可讀性呢?,有幾種重構(gòu)方案,接下來(lái)我會(huì)把這幾種方法都列出來(lái)

          第一種:使用枚舉

          枚舉(Enum)是Python自帶的特性,用來(lái)定義有多個(gè)有限值時(shí)是絕佳的應(yīng)用場(chǎng)景。先定義了狀態(tài)枚舉類

          import enum
          class StudyStatusEnum(enum.Enum):
              no_start = 0  # 未開始

              learning = 1  # 學(xué)習(xí)中

              finish = 2  # 已學(xué)完

              expired = 3 # 過(guò)期

          然后將前面的邏輯修改成:

          if status==StudyStatusEnum.no_start:
              pass



          elif status==StudyStatusEnum.leanring:
              pass



          if  finished:
              status = StudyStatusEnum.finish

          如果你的系統(tǒng)中用的ORM框架是SQLAlchemy,那么要同時(shí)修改status屬性的定義

          class Study(Models):
              # status = db.Column(db.SmallInteger, default=0, comment="學(xué)習(xí)狀態(tài) 0 未開始 1 學(xué)習(xí)中 2 已完成")

              status = db.Column(Enum(StudyStatusEnum), default=StudyStatusEnum.no_start)

          這樣修改其實(shí)有個(gè)問(wèn)題是,枚舉類型在數(shù)據(jù)庫(kù)中對(duì)應(yīng)的是字符串類型,而實(shí)際上我們希望存一個(gè)int類型,對(duì)應(yīng)枚舉的value值,而不是枚舉的name屬性。

          所以,這時(shí)候我們可以基于SQLAlchemy提供的TypeDecorator來(lái)自定義Enum類型叫做IntEnum。

          from sqlalchemy import TypeDecorator, Integer
          class IntEnum(TypeDecorator):
              """

              整數(shù)枚舉類型 主要用于狀態(tài)等場(chǎng)景



              """


              impl = Integer


              def __init__(self, enumtype, *args, **kwargs):
                  super().__init__(*args, **kwargs)
                  self._enumtype = enumtype


              def process_bind_param(self, value, dialect):
                  # 入庫(kù)時(shí)調(diào)用此方法,返回的是枚舉的value

                  return value.value


              def process_result_value(self, value, dialect):
                  # 從數(shù)據(jù)庫(kù)加載到內(nèi)存時(shí)的值,返回的一個(gè)枚舉實(shí)例

                  return self._enumtype(value)



          我們只需要重寫這三個(gè)方法,即可已實(shí)現(xiàn)一個(gè)可以保存int類型的枚舉。

          status = db.Column(IntEnum(StudyStatusEnum), default=StudyStatusEnum.no_start)

          第二種:使用常量

          直接將status所有可能的值用常量值代替

          NO_FINISH = 0

          LEARNING = 1

          FINISH = 2

          EXPRIED = 3




          if status== NO_FINISH:
              pass



          elif status==LEARNING:
              pass



          if  finished:
              status =FINISH

          這種也能提高可讀性,不過(guò)有個(gè)問(wèn)題是,如果有很多這樣的字段,不僅有學(xué)習(xí)狀態(tài),還有考試狀態(tài),如果每個(gè)狀態(tài)都有好幾個(gè)值,那么我們會(huì)定義很多個(gè)類似的常量值。

          而實(shí)際上這4個(gè)值都應(yīng)該是歸為一類的,就是學(xué)習(xí)狀態(tài),那么我們能不能歸類處理呢?

          答案就是用 namedtuple

          第三種:使用namedtuple

          namedtuple 是一個(gè)具名元組,就是一個(gè)帶有名字的元組,元組中的每個(gè)元素都對(duì)應(yīng)有一個(gè)名字,是不是非常適合用在這種場(chǎng)景?而且比用類和枚舉來(lái)表示更輕量級(jí)。

          from collections import namedtuple


          StudyStatus = namedtuple("StudyStatus""no_start, learning, finish, end")
          STUDY_STATUS = StudyStatus(0123)



          if status== STUDY_STATUS.no_start:
              pass



          elif status==STUDY_STATUS.learing:
              pass



          if  finished:
              status =STUDY_STATUS.finish

          這樣我們只需要定義一個(gè)枚舉常量對(duì)象,里面有4個(gè)值,分別代表4種不同的狀態(tài)。namedtuple 可以認(rèn)為是一個(gè)更輕量級(jí)的類,只有屬性沒有方法。

          用namedtuple來(lái)重構(gòu),而且還不需要修改Model層面的字段屬性,改動(dòng)最小,卻大大提高了可讀性。

          以上就是一個(gè)通過(guò)用namedtuple提高代碼可讀性的實(shí)踐案例??纯茨愕拇a中是不是充斥著這樣的代碼,也可以試著重構(gòu)一下。


          1. 一夜成名的航班追蹤網(wǎng)站,什么來(lái)頭?

          2. 記一次爬蟲APP逆向的詳細(xì)過(guò)程

          3. 在 Windows上寫 Python 代碼的最佳組合!

          瀏覽 59
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲AV成人精品一区二区三区_ | 久青草电影 | 操逼婷婷 | 国产久久久精品1000部视频 | 青青草偷拍视频 |