最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python 中 Meta Classes詳解

 更新時間:2016年02月13日 10:33:16   投稿:hebedich  
首先,在認(rèn)識metaclass之前,你需要認(rèn)識下python中的class。python中class的奇怪特性借鑒了smalltalk語言。大多數(shù)語言中,classes僅僅是用于描述怎樣創(chuàng)建一個對象的代碼端。在某種程度上說,python中的class也是這樣的。

接觸過 Django 的同學(xué)都應(yīng)該十分熟悉它的 ORM 系統(tǒng)。對于 python 新手而言,這是一項幾乎可以被稱作“黑科技”的特性:只要你在models.py中隨便定義一個Model的子類,Django 便可以:

  1. 獲取它的字段定義,并轉(zhuǎn)換成表結(jié)構(gòu)
  2. 讀取Meta內(nèi)部類,并轉(zhuǎn)化成相應(yīng)的配置信息。對于特殊的Model(如abstract、proxy),還要進(jìn)行相應(yīng)的轉(zhuǎn)換
  3. 為沒有定義objects的Model加上一個默認(rèn)的Manager

開發(fā)之余,我也曾腦補(bǔ)過其背后的原理。曾經(jīng),我認(rèn)為是這樣的:

啟動時,遍歷models.py中的所有屬性,找到Model的子類,并對其進(jìn)行上述的修改。
當(dāng)初,我還以為自己觸碰到了真理,并曾將其應(yīng)用到實際生產(chǎn)中——為 SAE 的 KVDB 寫了一個類 ORM 系統(tǒng)。然而在實現(xiàn)的過程中,我明顯感受到了這種方法的丑陋,而且性能并不出色(因為要遍歷所有的定義模塊)。

那么事實上,Django 是怎么實現(xiàn)的呢?

自古以來我們制造東西的方法都是“自上而下”的,是用切削、分割、組合的方法來制造。然而,生命是自下而上地,自發(fā)地建造起來的,這個過程極為低廉。
——王晉康 《水星播種》


這句話揭示了生命的神奇所在:真正的生命都是由基本物質(zhì)自發(fā)構(gòu)成的,而非造物主流水線式的加工。

那么,如果 類 也有生命的話,對它自己的修飾就不應(yīng)該由調(diào)用者來完成,而應(yīng)該是自發(fā)的。

幸而,python 提供了造物主的接口——這便是 Meta Classes,或者稱為“元類”。

元類 是什么?

簡單說:元類就是類的類。

首先,要有一個概念:

python 中,一切都是對象。

沒錯,一切,包括 類 本身。

既然,類 是 對象,對象 是 類的實例,那么——類 也應(yīng)該有 類 才對。

類的類:type

在 python 中,我們可以用type檢測一個對象的類,如:

print type(1) # <type 'int'>

如果對一個類操作呢?

print type(int) # <type 'type'>

class MyClass(object): pass

print type(MyClass) # <type 'type'>

print type(type) # <type 'type'>

這說明:type其實是一個類型,所有類——包括type自己——的類都是type。

type 簡介

從 官方文檔 中,我們可以知道:

和 dict 類似,type 也是一個工廠構(gòu)造函數(shù),調(diào)用其將返回 一個type類型的實例(即 類)。
type 有兩個重載版本:
+ `type(object)`,即我們最常用的版本。
+ `type(name, bases, dict)`,一個更強(qiáng)大的版本。通過指定 類名稱(`name`)、父類列表(`bases`)和 屬性字典(`dict`) 動態(tài)合成一個類。

下面兩個語句等價:

class Integer(int):

  name = 'my integer'

  def increase(self, num):
    return num + 1

  # -------------------

  Integer = type('Integer', (int, ), {
  'name': 'my integer',
  'increase': lambda self, num: \
          num + 1  # 很酷的寫法,不是么
  })

也就是說:類的定義過程,其實是type類型實例化的過程。

然而這和修飾一個已定義的類有什么關(guān)系呢?

當(dāng)然有啦~既然“類的定義”就是“type類型的初始化過程”,那其中必定會調(diào)用到type的構(gòu)造函數(shù)(__new__() 或 __init__())。只要我們繼承 type類 并修改其 __new__函數(shù),在這里面動手腳就可以啦。

接下來我們將通過一個栗子感受 python 的黑魔法,不過在此之前,我們要先了解一個語法糖。

__metaclass__ 屬性

有沒覺得上面第二段示例有些鬼畜呢?它勒令程序員將類的成員寫成一個字典,簡直是反人類。如果我們真的是要通過修改 元類 來改變 類 的行為的話,似乎就必須采用這種方法了~~簡直可怕~~

好在,python 2.2 時引進(jìn)了一個語法糖:__metaclass__。

class Integer(int):

  __metaclass__ = IntMeta

現(xiàn)在將會等價于:

Integer = IntMeta('Integer', (int, ), {})

由此一來,我們在使用傳統(tǒng)類定義的同時,也可以使用元類啦。

栗子:子類凈化器

需求描述

你是一個有語言潔癖的開發(fā)者,平時容不得別人講一句臟話,在開發(fā)時也是如此?,F(xiàn)在,你寫出了一個非常棒的框架,并馬上要將它公之于眾了。不過,你的強(qiáng)迫癥又犯了:如果你的使用者在代碼中寫滿了臟話,怎么辦?豈不是玷污了自己的純潔?
假如你就是這個喪心病狂的開發(fā)者,你會怎么做?

在知道元類之前,你可能會無從下手。不過,這個問題你可以用 元類 輕松解決——只要在類定義時過濾掉不干凈的字眼就好了(百度貼吧的干活~~)。

我們的元類看起來會是這樣的:

sensitive_words_list = ['asshole', 'fuck', 'shit']

def detect_sensitive_words(string):
  '''檢測敏感詞匯'''
  words_detected = filter(lambda word: word in string.lower(), sensitive_words_list)

  if words_detected:
    raise NameError('Sensitive words {0} detected in the string "{1}".' \
      .format(
        ', '.join(map(lambda s: '"%s"' % s, words_detected)),
        string
      )
    )

class CleanerMeta(type):

  def __new__(cls, class_name, bases, attrs):
    detect_sensitive_words(class_name) # 檢查類名
    map(detect_sensitive_words, attrs.iterkeys()) # 檢查屬性名

    print "Well done! You are a polite coder!" # 如無異常,輸出祝賀消息

    return super(CleanerMeta, cls).__new__(cls, class_name, bases, attrs)
    # 重要!這行一定不能漏?。∵@回調(diào)用內(nèi)建的類構(gòu)造器來構(gòu)造類,否則定義好的類將會變成 None
現(xiàn)在,只需這樣定義基類:

class APIBase(object):

  __metaclass__ = CleanerMeta

  # ...
那么所有 APIBase 的派生類都會接受安全審查(奸笑~~):

class ImAGoodBoy(APIBase):

  a_polite_attribute = 1

# [Output] Well done! You are a polite coder!

class FuckMyBoss(APIBase):

  pass

# [Output] NameError: Sensitive words "fuck" detected in the string "FuckMyBoss".

class PretendToBePolite(APIBase):

  def __fuck_your_asshole(self):
    pass

# [Output] NameError: Sensitive words "asshole", "fuck" detected in the string "_PretendToBePolite__fuck_your_asshole".

看,即使像最后一個例子中的私有屬性也難逃審查,因為它們本質(zhì)都是相同的。

甚至,你還可以對有問題的屬性進(jìn)行偷偷的修改,比如 讓不文明的函數(shù)在調(diào)用時打出一行警告 等等,這里就不多說了。

元類 在實際開發(fā)中的應(yīng)用

日常開發(fā)時,元類 常用嗎?

當(dāng)然,Django 的 ORM 就是一個例子,大名鼎鼎的 SQLAlchemy 也用了這種黑魔法。

此外,在一些小型的庫中,也有 元類 的身影。比如 abc(奇怪的名字~~)——這是 python 的一個內(nèi)建庫,用于模擬 抽象基類(Abstract Base Classes)。開發(fā)者可以使用 abc.abstractmethod 裝飾器,將 指定了 __metaclass__ = abc.ABCMeta 的類的方法定義成 抽象方法,同時這個類也成了 抽象基類,抽象基類是不可實例化的。這便實現(xiàn)了對 抽象基類 的模擬。

倘若你也有需要動態(tài)修改類定義的需求,不妨也試試這種“黑魔法”。

小結(jié)

  1. 類 也是 對象,所有的類都是type的實例
  2. 元類(Meta Classes)是類的類
  3. __metaclass__ = Meta 是 Meta(name, bases, dict) 的 語法糖
  4. 可以通過重載元類的 __new__ 方法,修改 類定義 的行為

相關(guān)文章

  • Jupyter notebook 不自動彈出網(wǎng)頁的解決方案

    Jupyter notebook 不自動彈出網(wǎng)頁的解決方案

    這篇文章主要介紹了Jupyter notebook 不自動彈出網(wǎng)頁的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-05-05
  • 利用python生成照片墻的示例代碼

    利用python生成照片墻的示例代碼

    這篇文章主要介紹了利用python生成照片墻的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • Python獲取excel的數(shù)據(jù)并繪制箱型圖和直方圖的方法實例

    Python獲取excel的數(shù)據(jù)并繪制箱型圖和直方圖的方法實例

    這篇文章主要給大家介紹了關(guān)于Python獲取excel的數(shù)據(jù)并繪制箱型圖和直方圖的相關(guān)資料,好的圖表能幫助我們深化數(shù)據(jù)的記憶點,文中通過圖文以及代碼示例將實現(xiàn)的方法介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • python使用pandas按照行數(shù)分割表格

    python使用pandas按照行數(shù)分割表格

    本文主要介紹了python使用pandas按照行數(shù)分割表格,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Django如何利用uwsgi和nginx修改代碼自動重啟

    Django如何利用uwsgi和nginx修改代碼自動重啟

    這篇文章主要介紹了Django如何利用uwsgi和nginx修改代碼自動重啟問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Python編程快速上手——強(qiáng)口令檢測算法案例分析

    Python編程快速上手——強(qiáng)口令檢測算法案例分析

    這篇文章主要介紹了Python強(qiáng)口令檢測算法,結(jié)合實例形式分析了Python針對密碼口令強(qiáng)度檢測的相關(guān)算法實現(xiàn)技巧,需要的朋友可以參考下
    2020-02-02
  • python 實現(xiàn)方陣的對角線遍歷示例

    python 實現(xiàn)方陣的對角線遍歷示例

    今天小編就為大家分享一篇python 實現(xiàn)方陣的對角線遍歷示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • 微信跳一跳輔助python代碼實現(xiàn)

    微信跳一跳輔助python代碼實現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了微信跳一跳輔助的python代碼實現(xiàn)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 30道python自動化測試面試題與答案匯總

    30道python自動化測試面試題與答案匯總

    對于機(jī)器學(xué)習(xí)算法工程師而言,Python是不可或缺的語言,它的優(yōu)美與簡潔令人無法自拔,下面這篇文章主要給大家介紹了關(guān)于30道python自動化測試面試題與答案匯總的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • python使用Turtle庫繪制動態(tài)鐘表

    python使用Turtle庫繪制動態(tài)鐘表

    這篇文章主要為大家詳細(xì)介紹了python使用Turtle庫繪制動態(tài)鐘表,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11

最新評論

义马市| 白城市| 张家界市| 开远市| 石家庄市| 璧山县| 原平市| 通海县| 闵行区| 晋江市| 汝南县| 连云港市| 辽中县| 彭山县| 阿瓦提县| 临江市| 衡阳市| 宁明县| 冷水江市| 丹阳市| 辽阳市| 盖州市| 广灵县| 图片| 彭泽县| 临朐县| 麻栗坡县| 象州县| 高淳县| 肥西县| 太保市| 兴仁县| 本溪| 杭锦旗| 东安县| 三都| 桂阳县| 清苑县| 敦化市| 濮阳市| 武功县|