用来表示python代码块的是什么_三分钟带你用简单的Python代码深入理解Python中的元类...
互聯(lián)網(wǎng)的數(shù)據(jù)爆炸式的增長,而利用 Python 爬蟲我們可以獲取大量有價值的數(shù)據(jù)
類也是對象
在理解元類前,需要先掌握Python中的類。在大多數(shù)編程語言中,類就是一組描述如何生成對象的代碼段。在Python中這一點仍然成立:
但是,Python中的類遠不止如此。類也是一種對象(實例)。是的,沒錯,就是對象。只要使用關鍵字class,Python解釋器在執(zhí)行時就會創(chuàng)建一個類對象。
上述代碼在內存中創(chuàng)建一個名為ObjectCreator的類對象。只不過這個對象(類)擁有創(chuàng)建對象(類實例)的能力,而這也是它是一個類的原因。但是,ObjectCreator本質上仍然是一個對象,可以對它做如下的操作:
動態(tài)創(chuàng)建類
因為類也是對象,所以可以在運行時動態(tài)的創(chuàng)建它們,就像其他對象一樣。可以在函數(shù)中創(chuàng)建類,使用class關鍵字即可。
由于類也是對象,所以它們也是通過什么東西來生成的。還記得內建函數(shù)type嗎?這個古老但強大的函數(shù)能夠讓你知道一個對象的類型是什么,就像這樣:
type還有一種完全不同的能力,它也能動態(tài)的創(chuàng)建類。type可以接受一個類的描述作為參數(shù),然后返回一個類。(根據(jù)傳入?yún)?shù)的不同,同一個函數(shù)擁有兩種完全不同的用法是一件很傻的事情,但這在Python中是為了保持向后兼容性.)
type可以像這樣工作
如下面的代碼
等價于
type 接受一個字典來為類定義類屬性,因此
可以翻譯為
并且可以將Foo當成一個普通的類一樣使用
當然,也可以繼承這個類,如下代碼
也可以寫成
也可以為類增加方法
在Python中,類也是對象,可以動態(tài)的創(chuàng)建類。這就是當你使用關鍵字class時Python在幕后做的事情,這些是通過元類實現(xiàn)的。
什么是元類
元類就是用來創(chuàng)建類的“東西”。創(chuàng)建類是為了創(chuàng)建類的實例對象。但是我們已經(jīng)知道了Python中的類也是對象。元類就是用來創(chuàng)建這些類(對象)的,元類就是類的類,簡而言之,元類是用來創(chuàng)建和管理類對象的。可以這樣理解:
ype可以讓你這樣創(chuàng)建一個類
**這是因為type是一個元類。**type就是Python在背后用來創(chuàng)建所有類的元類。
type就是創(chuàng)建類對象的類。可以通過__class__屬性來看到這一點。Python中所有的東西,注意,是指所有的東西—都是對象。這包括整數(shù)、字符串、函數(shù)以及類。它們全部都是對象,而且它們都是從一個類創(chuàng)建而來的。
那么對于任何一個__class__的__class__屬性又是什么呢?
因此,元類就是用來創(chuàng)建類對象的。如果你喜歡的話,可以把元類稱為“類工廠”(不要和工廠類搞混了)。?type就是Python的內建元類,當然,你也可以自定義元類。
__metaclass__屬性
可以在定義類的時候為其添加__metaclass__屬性。
如果你這么做了,Python就會用指定的元類來創(chuàng)建類。
小心點,這里面有些技巧。首先寫下class Foo(object),但是類對象Foo還沒有在內存中創(chuàng)建。Python會在類的定義中尋找__metaclass__屬性,如果找到了,Python就會用它來創(chuàng)建類Foo,如果沒有找到,就會用內建的type來創(chuàng)建這個類。
當你寫如下代碼時 :
Python做了如下的操作:
自定義元類
元類是用來創(chuàng)建和管理類對象的。
__metaclass__不一定是個類,函數(shù)也可以- -! 這里先以一個簡單的函數(shù)作為例子開始。
這一次用一個真正的class來做元類。
請記住,’type’實際上是一個類,就像’str’和’int’一樣,可以從type繼承。
自定義元類時,通常會繼承type,并重新實現(xiàn)__init__()或__new__()等方法。
在這里,創(chuàng)建的對象是類,我們希望能夠自定義它,所以我們這里改寫__new__ ,如果需要的話,也可以在__init__中做些事情。
你可能已經(jīng)注意到了有個額外的參數(shù)upperattr_metaclass,這并沒有什么特別的。類方法的第一個參數(shù)總是表示當前的實例,就像在普通的類方法中的self參數(shù)一樣。當然了,為了清晰起見,這里的名字起的比較長。就像self一樣,所有的參數(shù)都有它們的傳統(tǒng)名稱。因此,一個元類應該是這樣的:
如果使用super方法的話,還可以使它變得更清晰一些。
再來個例子,定義一個元類,用來檢查類對象中的方法是否定義了__doc__
未定義__doc__
定義了__doc__
除此之外,關于元類沒有別的可說的了。使用到元類的代碼比較復雜,這背后的原因倒并不是因為元類本身,而是因為通常會使用元類去做一些晦澀的事,依賴于自省,控制繼承等等。確實,用元類來搞些“黑魔法”是特別有用的,但是搞出的東西都很復雜。就元類本身而言,它們其實是很簡單的:
1) 攔截類的創(chuàng)建;
2) 修改和檢查類;
3) 返回修改之后的類;
究竟為什么要使用元類?
現(xiàn)在回到我們的大主題,為什么要去使用這種容易出錯且難懂的特性?好吧,一般來說,你根本就用不上它。
“元類就是黑魔法,99%的用戶根本不必為此操心。如果你想搞清楚究竟是否需要用到元類,那么你就不需要它。那些實際用到元類的人都非常清楚地知道他們需要做什么,而且根本不需要解釋為什么要用元類。“ —— Python界的領袖 Tim Peters
元類的主要用途是創(chuàng)建API。一個典型的例子是Django ORM。它允許像這樣定義:
但是如果像這樣做的話:
這并不會返回一個IntegerField對象,而是會返回一個int,甚至可以直接從數(shù)據(jù)庫中取出數(shù)據(jù)。這是有可能的,因為models.Model定義了__metaclass__, 并且使用了一些魔法能夠將你剛剛定義的簡單的Person類轉變成對數(shù)據(jù)庫的一個復雜hook。Django框架將這些看起來很復雜的東西通過暴露出一個簡單的使用元類的API將其化簡,通過這個API重新創(chuàng)建代碼,在背后完成真正的工作。
結語
首先,你知道了類是能夠創(chuàng)建出類實例的對象。好吧,事實上,類本身也是實例,當然,它們是元類的實例。
總結
以上是生活随笔為你收集整理的用来表示python代码块的是什么_三分钟带你用简单的Python代码深入理解Python中的元类...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 女主星际种植文有哪些 女主星际种植文简介
- 下一篇: 含根号的导数怎么求_数学分析Mathem