<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>

          Python 中最黑魔法、最難懂的概念

          共 5400字,需瀏覽 11分鐘

           ·

          2021-06-19 17:28

          大家好,我是老胡

          最近在看一個(gè)開(kāi)源框架的源碼,其中大量使用了 metaclass 方法。這個(gè)概念非常抽象,本文我就以一個(gè)有趣實(shí),用更簡(jiǎn)潔和通暢的方式來(lái)理解它。

          元類 ( metaclass )應(yīng)該是 Python 中最黑魔法、最難懂的概念之一,它提供了創(chuàng)造新類型的能力,為程序設(shè)計(jì)帶來(lái)更多可能性。不少功能強(qiáng)大的開(kāi)發(fā)框架,內(nèi)部實(shí)現(xiàn)離不開(kāi) metaclass 的魔法。

          Class

          面向?qū)ο缶幊套钪匾母拍罹褪穷悾–lass)和實(shí)例(Instance),我們先來(lái)創(chuàng)建一個(gè) Lxs 的類,它有兩個(gè)基本功 sing 和 dance ,lxs 是這個(gè)類的實(shí)例:

          class Lxs(object): 
              def __init__(self, name, duration):
                  self.name = name
                  self.duration = duration
                  print('%s practiced %s years' % (self.name, self.duration))
              def sing(self):
                  print('%s good at singing' % self.name)

              def dance(self):
                  print('%s good at dancing' % self.name)

          lxs = Lxs('laohu',1.5)
          lxs.sing()
          lxs.dance()

          練習(xí)時(shí)常1年半的老胡擅長(zhǎng)唱和跳
          恩,針不戳!

          laohu practiced 1.5 years
          laohu good at singing
          laohu good at dancing

          再來(lái)用__class__屬性或type()看看 Lxs 和 lxs 分別是誰(shuí)創(chuàng)建的

          print(lxs.__class__)
          print(Lxs.__class__)

          lxs 是 Lxs 的實(shí)例,它創(chuàng)建自 Lxs ,這很容易理解。

          我們 Lxs 類是 type 創(chuàng)建的?

          <class '__main__.Lxs'>
          <class 'type'>

          一切對(duì)象都來(lái)自 type

          先說(shuō)結(jié)論:type 可以動(dòng)態(tài)創(chuàng)建 類(class) ,對(duì)象是類(class)的實(shí)例,類(class)也是對(duì)象,是 type 的實(shí)例。type 為對(duì)象的頂點(diǎn),所有對(duì)象都創(chuàng)建自 type 。

          當(dāng)使用 type 創(chuàng)建 class 時(shí),其用法如下:

          class = type(classname, superclasses, attributedict)
          '''
          classname:類名
          superclasses:類的繼承關(guān)系,用元組表示
          attributedict:表示各種屬性、方法,用字典表示
          '
          ''

          繼續(xù)上例,先定義__init__,sing 和 dance ,然后用 type 可以創(chuàng)建和上面完全一樣的類:

          Lxs = type('Lxs', (object,), dict( __init__= __init__,sing=sing,dance=dance))
          lxs = Lxs('laohu',1)
          lxs.sing()
          print(lxs.__class__)
          print(Lxs.__class__)

          這里不得不提一下__call__這個(gè)屬性
          此方法會(huì)在實(shí)例作為一個(gè)函數(shù)被“調(diào)用”時(shí)被調(diào)用
          這里等號(hào)右邊的type(classname, superclasses, attributedict),就是 type 的__call__運(yùn)算符重載,它會(huì)進(jìn)一步調(diào)用:

          type.__new__(typeclass, classname, superclasses, attributedict)
          type.__init__(class, classname, superclasses, attributedict)
          # 這一部分我們以后有空再細(xì)品

          總結(jié)一下:type 實(shí)際上是 Python 創(chuàng)建所有 class 的 metaclass。

          metaclass

          除了使用type()動(dòng)態(tài)創(chuàng)建類以外,要控制類的創(chuàng)建行為,還可以使用metaclass。

          先定義metaclass,就可以創(chuàng)建類,最后創(chuàng)建實(shí)例。

          一句話:metaclass 是 type 的子類,是類的模板

          metaclass 的主要目的是在 class 被創(chuàng)建的時(shí)候?qū)ι傻?class 進(jìn)行自動(dòng)的動(dòng)態(tài)修改。

          舉個(gè)例子:像老胡就只會(huì) sing 和 dance,有人還會(huì)rap,有人會(huì)說(shuō)相聲,我們定義很多的 class ,有一天,一個(gè)男人橫空出世,他會(huì)打籃球!然后,所有的練習(xí)生也都學(xué)會(huì)了籃球,這可怎么修改?

          metaclass 就可以施展魔法了

          class LxsMetaclass(type):
              def __new__(cls, cls_name, bases, attrs):
                  def basketball(self):
                      print('%s good at basketball' % self.name)
                  attrs['basketball'] = basketball
                  return super(LxsMetaclass, cls).__new__(cls, cls_name, bases, attrs)

          它指示Python解釋器在創(chuàng)建 LxsMetaclass 時(shí),要通過(guò)LxsMetaclass.new()來(lái)創(chuàng)建,在此,我們可以修改類的定義,比如,加上新的方法basketball(),然后,返回修改后的定義。

          我們用 LxsMetaclass 這個(gè)模板創(chuàng)建類:

          class Cxk(object, metaclass=LxsMetaclass):
              def __init__(self, name, duration):
                  self.name = name
                  self.duration = duration
                  print('%s practiced %s years' % (self.name, self.duration))
              
              def sing(self):
                  print('%s good at singing' % self.name)
              
              def dance(self):
                  print('%s good at  dancing' % self.name)
              
              def rap(self):
                  print('%s good at  rap' % self.name)

              
          cxk = Cxk('cxk',2.5)
          cxk.basketball()

          運(yùn)行結(jié)果如下,秀?

          cxk practiced 2.5 years
          cxk good at basketball


          不過(guò)metaclass的作用肯定不限于此,舉個(gè)例子,也算是個(gè)思考題,大家品一品。

          比如 laohu 化身 xck 的粉絲,打著學(xué)籃球的幌子學(xué) sing、dance和rap  :

          class Funs(Cxk):
              def basketball(self):
                  print('%s good at  singing&dancing&rap' % self.name)


          fans = Funs('laohu',0.5)
          fans.basketball()

          運(yùn)行結(jié)果會(huì)是什么呢?

          laohu practiced 0.5 years
          laohu good at basketball

          laohu 真的就只學(xué)會(huì)了籃球。。。

          這是為何呢?且聽(tīng)下回分解。

          兄弟們,來(lái)個(gè)三連可好?轉(zhuǎn)發(fā),在看,點(diǎn)贊

          ···  END  ···
          推薦閱讀:
          一、Number(數(shù)字)
          Python基礎(chǔ)之?dāng)?shù)字(Number)超級(jí)詳解
          Python隨機(jī)模塊22個(gè)函數(shù)詳解
          Python數(shù)學(xué)math模塊55個(gè)函數(shù)詳解
          二、String(字符串)
          Python字符串的45個(gè)方法詳解
          Pandas向量化字符串操作
          三、List(列表)
          超級(jí)詳解系列-Python列表全面解析
          Python輕量級(jí)循環(huán)-列表推導(dǎo)式
          四、Tuple(元組)
          Python的元組,沒(méi)想象的那么簡(jiǎn)單
          五、Set(集合)
          全面理解Python集合,17個(gè)方法全解,看完就夠了
          六、Dictionary(字典)
          Python字典詳解-超級(jí)完整版
          七、內(nèi)置函數(shù)
          Python初學(xué)者必須吃透這69個(gè)內(nèi)置函數(shù)!
          八、正則模塊
          Python正則表達(dá)式入門到入魔
          筆記 | 史上最全的正則表達(dá)式
          八、系統(tǒng)操作
          Python之shutil模塊11個(gè)常用函數(shù)詳解
          Python之OS模塊39個(gè)常用函數(shù)詳解
          九、進(jìn)階模塊
          【萬(wàn)字長(zhǎng)文詳解】Python庫(kù)collections,讓你擊敗99%的Pythoner
          高手如何在Python中使用collections模塊

          掃描關(guān)注本號(hào)↓

          瀏覽 49
          點(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>
                  国产高清无码免费视频 | 久久妻视频免费精品人妻中文无码 | 亚洲欧美日韩中文在线 | 91亚洲国产成人久久精品麻豆 | 丁香五月婷婷香 |