<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 中最黑魔法、最難懂的概念

          共 4980字,需瀏覽 10分鐘

           ·

          2021-05-07 03:59

          大家好,我是老胡

          最近在看一個開源框架的源碼,其中大量使用了 metaclass 方法。這個概念非常抽象,本文我就以一個有趣實,用更簡潔和通暢的方式來理解它。

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

          Class

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

          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í)時常1年半的老胡擅長唱和跳
          恩,針不戳!

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

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

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

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

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

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

          一切對象都來自 type

          先說結(jié)論:type 可以動態(tài)創(chuàng)建 類(class) ,對象是類(class)的實例,類(class)也是對象,是 type 的實例。type 為對象的頂點,所有對象都創(chuàng)建自 type 。

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

          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__這個屬性
          此方法會在實例作為一個函數(shù)被“調(diào)用”時被調(diào)用
          這里等號右邊的type(classname, superclasses, attributedict),就是 type 的__call__運算符重載,它會進一步調(diào)用:

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

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

          metaclass

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

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

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

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

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

          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 時,要通過LxsMetaclass.new()來創(chuàng)建,在此,我們可以修改類的定義,比如,加上新的方法basketball(),然后,返回修改后的定義。

          我們用 LxsMetaclass 這個模板創(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()

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

          cxk practiced 2.5 years
          cxk good at basketball


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

          比如 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()

          運行結(jié)果會是什么呢?

          laohu practiced 0.5 years
          laohu good at basketball

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

          - EOF -


          回復(fù)關(guān)鍵字“簡明python ”,立即獲取入門必備書籍簡明python教程》電子版

          回復(fù)關(guān)鍵字爬蟲”,立即獲取爬蟲學(xué)習(xí)資料

          點擊關(guān)注【python入門與進階】,閱讀更多精彩內(nèi)容
          ??????
          瀏覽 29
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  丝袜美腿一区 | 啪啪啪啪啪啪网站 | 4438成人网站 | 欧美成人一二三区 | 日韩精品人妻无码 |