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

Python探索之Metaclass初步了解

 更新時間:2017年10月28日 10:17:47   作者:西北那個峰  
本文先簡單介紹了Python中的類,然后是主要內(nèi)容,涉及Metaclass的相關內(nèi)容,還是不錯的,這里分享給大家,供需要的朋友參考。

先以一個大牛的一段關于Python Metapgramming的著名的話來做開頭:

Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why). – Tim Peters

翻譯一下:Metaclasses是99%的用戶都無需費神的黑科技。如果你還在糾結(jié)你是不是需要它的話,答案是NO (真正需要的人根本不需要解釋) – Tim Peters

這是什么鬼話?道可道,非常道嗎?

Meta?

好,裝B已畢。這確實是一個冷僻的,不常用的話題。一篇短文肯定講不完。 所以叫做初步了解。

python中的類

首先這里討論的python類,都基于繼承于object的新式類進行討論。

首先在python中,所有東西都是對象。這句話非常重要要理解元類我要重新來理解一下python中的類

class Trick(object):
  pass

當python在執(zhí)行帶class語句的時候,會初始化一個類對象放在內(nèi)存里面。例如這里會初始化一個Trick對象

這個對象(類)自身擁有創(chuàng)建對象(通常我們說的實例,但是在python中還是對象)的能力。

為了方便后續(xù)理解,我們可以先嘗試一下在新式類中最古老厲害的關鍵字type。

input:
class Trick(object):
pass
print type('123')
print type(123)
print type(Trick())
output:
<type 'str'>
<type 'int'>
<class '__main__.Trick'>

可以看到能得到我們平時使用的 str, int, 以及我們初始化的一個實例對象Trick()

但是下面的方法你可能沒有見過,type同樣可以用來動態(tài)創(chuàng)建一個類

type(類名, 父類的元組(針對繼承的情況,可以為空),包含屬性的字典(名稱和值))

英文meta這個詞其實是從希臘語里面借來的。wikipedia上的解釋是:

indicate a concept which is an abstraction behind another concept, used to complete or add to the latter

不看還好,其實看了更暈。好在后面的解釋有一句“更高一層的抽象”,可以幫助理解。 其實我們可以這樣理解。meta的意思就是“關于什么的什么”:比如metadata可以理解為“關于數(shù)據(jù)的數(shù)據(jù)”,metaprogramming可以理解為“關于編程的編程”。這就和“更高一層的抽象” 比較契合了。同時又隱隱和編程中的另一個永恒主題-recursion聯(lián)系在了一起。

另外,meta這個詞天朝這邊翻譯成“元”,海峽對岸翻譯成“后設”。其實我都不大理解從何而來。

元類一般用于創(chuàng)建類。在執(zhí)行類定義時,解釋器必須要知道這個類的正確的元類。解釋器會先尋找類屬性__metaclass__,如果此屬性存在,就將這個屬性賦值給此類作為它的元類。如果此屬性沒有定義,它會向上查找父類中的__metaclass__.如果還沒有發(fā)現(xiàn)__metaclass__屬性,解釋器會檢查名字為__metaclass__的全局變量,如果它存在,就使用它作為元類。否則, 這個類就是一個傳統(tǒng)類,并用 types.ClassType 作為此類的元類。

在執(zhí)行類定義的時候,將檢查此類正確的(一般是默認的)元類,元類(通常)傳遞三個參數(shù)(到構造器): 類名,從基類繼承數(shù)據(jù)的元組,和(類的)屬性字典。

實例

聚焦到我們今天的主題,metaprogramming就是編寫用來生成代碼的代碼。

假設我們寫了一個NB的函數(shù),用來計算一個任意復雜的算數(shù)表達式的值:

像1+2, 3*6+10, 什么的都可以交給它去計算。這樣的函數(shù)的算法不是我們的主題,所以我們請出python自帶的大招eval(),一行就可以搞定了:

def calc(expression):
  return eval(expression)

因為輸入的可能性是無限的,所以我們肯定要好好測試一下這個函數(shù)了。假定我們想了 上百個test case。又假定我們是用unittest這個module來做測試的。這樣的測試程序一般會長成這樣:

import unittest
class TestStringMethods(unittest.TestCase):
  def test_upper(self):
    self.assertEqual('foo'.upper(), 'FOO')
  def test_isupper(self):
    self.assertTrue('FOO'.isupper())
    self.assertFalse('Foo'.isupper())
  def test_split(self):
    s = 'hello world'
    self.assertEqual(s.split(), ['hello', 'world'])
    # check that s.split fails when the separator is not a string
    with self.assertRaises(TypeError):
      s.split(2)
if __name__ == '__main__':
  unittest.main()

所以我們的目的就是用metaprogramming的方式來自動產(chǎn)生類似上面的測試類。

先上程序后解釋:

#!/usr/bin/python3
import unittest
def calc(expression):
  return eval(expression)
def add_test(name, asserts):
  def test_method(asserts):
    def fn(self):
      left, right = asserts.split('=')
      expected = str(calc(left))
      self.assertEqual(expected, right)
    return fn
  d = {'test1': test_method(asserts)}
  cls = type(name, (unittest.TestCase,), d)
  globals()[name] = cls
if __name__ == '__main__':
  for i, t in enumerate([
      "1+2=3",
      "3*5*6=90"]):
    add_test("Test%d" % i, t)
  unittest.main()

NB的calc()函數(shù)我們解釋過了。main這段也比較簡單:我們用聲明的方式定義了一組測試,然后通過unittest來執(zhí)行。

有點復雜的是add_test()。我們先來看看最內(nèi)層的fn(self)這個方法。邏輯上,它就是把輸入的測試用例分成兩份,一份是calc()的輸入,一份是我們期待的結(jié)果;然后調(diào)用calc(), 接著用assertEqual()來測試。

但是這個self有點奇怪 – 這里沒有類,哪里來的self? 其實fn(self)確實是一個類的方法,只不過這個類是我們通過代碼動態(tài)生成的。也就是下面這一行:

cls = type(name, (unittest.TestCase,), d)

這里的type()就是通常我們用來檢查某個變量的類型的那個函數(shù)。只不過它還有另外一種不大為人知的形式:

class type(name, bases, dict)

這第二種形式,就會產(chǎn)生一個新的類型。以我們的程序為例,就是以unit.TestCase為baseclass, 產(chǎn)生了一個名為TestN的新類型,改類型的實現(xiàn)由d給出,而d就包含了通過closure返回的fn(self)這個方法。只不過在這個新類里面,它的名字叫做 test1()。

最后,我們把這個新產(chǎn)生的類加入到當前全局符號表里面,也就相當于上面給出的unittest的例子。

所以,總結(jié)一下。當我們運行這個腳本的時候,這段比較短的代碼會針對每一個測試的表達式產(chǎn)生一個新的測試類,并動態(tài)生成測試的方法加載到該類里面。unitest從globals中找到這些類并一一執(zhí)行測試。

上面的例子中,其實一行一行手打calc(1+2) == 3也沒什么大不了的。但是當你要表達的邏輯比較復雜的時候,metaprogramming的強大就體現(xiàn)出來了。

總結(jié)

那么,看完這篇文章,我們也成為Tim所說的1%的程序猿了!其實,也許他的意思是,99%的編程工作都用不到這樣技巧。在一些特殊的場合,比如編寫某種框架的時候,metaprogramming會做到事半功倍。祝你在實踐中碰到這樣的機會。

以上就是本文關于Python探索之Metaclass初步了解的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站:Python編程之Re模塊下的函數(shù)介紹python中模塊的__all__屬性詳解等,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

相關文章

  • Python一行代碼實現(xiàn)生成和讀取二維碼

    Python一行代碼實現(xiàn)生成和讀取二維碼

    二維碼被稱為快速響應碼,可能看起來很簡單,但它們能夠存儲大量數(shù)據(jù)。無論掃描二維碼時包含多少數(shù)據(jù),用戶都可以立即訪問信息。本文將用一行Python代碼實現(xiàn)二維碼的讀取與生成,需要的可以參考一下
    2022-02-02
  • Python利用tkinter實現(xiàn)一個簡易番茄鐘的示例代碼

    Python利用tkinter實現(xiàn)一個簡易番茄鐘的示例代碼

    番茄鐘是番茄工作法使用的一個時間表,即選擇一個待完成的任務,將番茄時間設為25分鐘,專注工作,中途不允許做任何與該任務無關的事,直到番茄時鐘響起,然后在紙上畫一個X短暫休息一下。本文用tkinter實現(xiàn)一個簡易番茄鐘,需要的可以參考一下
    2022-12-12
  • 解決Python安裝后pip不能用的問題

    解決Python安裝后pip不能用的問題

    今天小編就為大家分享一篇解決Python安裝后pip不能用的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • matplotlib多子圖實現(xiàn)共享坐標軸的示例詳解

    matplotlib多子圖實現(xiàn)共享坐標軸的示例詳解

    這篇文章主要為大家詳細介紹了matplotlib繪制多子圖師如何實現(xiàn)共享坐標軸,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-02-02
  • python監(jiān)控日志中的報錯并進行郵件報警

    python監(jiān)控日志中的報錯并進行郵件報警

    這篇文章主要為大家介紹了python監(jiān)控日志中的報錯并進行郵件報警的實現(xiàn)實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • 基于Python List的賦值方法

    基于Python List的賦值方法

    今天小編就為大家分享一篇基于Python List的賦值方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • Python如何獲取模塊中類以及類的屬性方法信息

    Python如何獲取模塊中類以及類的屬性方法信息

    python對屬性權限的控制是通過屬性名來實現(xiàn)的,下面這篇文章主要給大家介紹了關于Python如何獲取模塊中類以及類的屬性方法信息的相關資料,需要的朋友可以參考下
    2021-12-12
  • 關于Matplotlib繪制動態(tài)實時曲線的方法改進指南

    關于Matplotlib繪制動態(tài)實時曲線的方法改進指南

    這篇文章主要給大家介紹了關于Matplotlib繪制動態(tài)實時曲線的相關資料,matplotlib是python里最popular的畫圖工具,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-06-06
  • Python巧用SnowNLP實現(xiàn)生成srt字幕文件

    Python巧用SnowNLP實現(xiàn)生成srt字幕文件

    SnowNLP是一個可以方便的處理中文文本內(nèi)容的python類庫,本文主要為大家詳細介紹了Python如何巧用SnowNLP實現(xiàn)將一段話一鍵生成srt字幕文件,感興趣的可以了解下
    2024-01-01
  • Python中的查找算法代碼實例

    Python中的查找算法代碼實例

    這篇文章主要介紹了Python中的查找算法代碼實例,算法是解決一系列問題的清晰指令,也就是,能對一定規(guī)范的輸入,在有限的時間內(nèi)獲得所要求的輸出,簡單來說,算法就是解決一個問題的具體方法和步驟,算法是程序的靈魂,需要的朋友可以參考下
    2023-07-07

最新評論

大城县| 鸡西市| 湛江市| 寿光市| 留坝县| 陵川县| 霍城县| 吉木萨尔县| 改则县| 海宁市| 砀山县| 安化县| 郯城县| 安图县| 青冈县| 铜山县| 红桥区| 尉犁县| 松滋市| 文安县| 山阳县| 石渠县| 黔江区| 新余市| 长宁区| 加查县| 柘荣县| 辽阳市| 四川省| 望江县| 花莲市| 乐安县| 盐津县| 沂水县| 察隅县| 溧水县| 龙里县| 谷城县| 黄平县| 棋牌| 苍山县|