python元類淺析
宣告:本文僅限於簡書釋出,其他第三方網站均為盜版,原文地址: python元類淺析
在 python 的新式類中,元類可能是最難以理解的功能之一了,不僅元類這個概念難以理解,而且很多講解和闡述也是說得雲裡霧裡,我看過很多很多篇關於元類和 metaclass 的介紹,但是依舊不是很懂,知道我硬著頭皮看了兩篇官方的解析之後,才有點理解了,本文我將嘗試以一個比較簡單的角度來介紹元類,希望不會像我看過的文章一樣讓讀者也在雲裡霧裡。
什麼是元類
可能我們在學習 Python 的過程中,我們經常會聽過一個概念,那就是“在Python 中,一切都是物件”,那麼類呢?類也是物件麼?是的,類也是物件,那麼類既然是物件的話,它是誰的物件?
這個概念可能有點拗口,但是,事實上類是元類的物件,也就是類的類。元類的例項是類,類的例項是物件,就這麼簡單,我們可以這麼驗證:
奇怪了對吧,對於 3 中的 a 的型別是 A,我們毫無異議,但是 A 的型別是 type 是什麼回事,那我們就反推一下,是不是可以這麼理解:
對,就是這麼理解,我們稱 a 是類 A 的物件,那麼,我們也要稱 A 是 type 的物件,那麼我們就可以將這裡的 type 理解為類的類,也就是大家所說的 元類 了。根據 Python 的官方文件[3],完整的構造形式是這樣的:
A = type('A', (object, ), dict({}))
class type(name, bases, dict)
With one argument, return the type of an object. The return value is a type object and generally the same object as returned by object.class.
The isinstance() built-in function is recommended for testing the type of an object, because it takes subclasses into account.
With three arguments, return a new type object. This is essentially a dynamic form of the class statement. The name string is the class name and becomes the __name__ attribute; the bases tuple itemizes the base classes and becomes the __bases__ attribute; and the dict dictionary is the namespace containing definitions for class body and is copied to a standard dictionary to become the __dict__ attribute. For example, the following two statements create identical type objects:
元類何時用
雖然,剛才演示的是用 type 來構造類,但是,這並不是 Python 的常用用法,因為這種用法比較麻煩,而且侷限性比較大。既然是類的類,我們從上面看到,他可以建立類,那麼,能不能不建立類,而只修改類的屬性呢?事實上,Python 是可以的,根據 Python 官方文件[4] 所描述,預設情況下,類似通過 type()
來構建的;但是我們也可以通過在定義類的時候指定 metaclass
引數,來修改類的建立過程:
如何確定元類
可能你會奇怪,還需要知道如何確定元類?一個類的元類不是很明確嗎?不一定哦,就以我們上面一個例子來說,我們可以很明確知道 MyClass
的元類是 Meta
,那麼 MySubclass
的元類呢?好像一下子不能肯定得答上來,下面再看看別人怎麼說,還是參考文件[4]:
The appropriate metaclass for a class definition is determined as follows:
- if no bases and no explicit metaclass are given, then type() is used
- if an explicit metaclass is given and it is not an instance of type(), then it is used directly as the metaclass
- if an instance of type() is given as the explicit metaclass, or bases are defined, then the most derived metaclass is used
根據這些規則,我們就可以清晰得知道,我們的 MySubclass
的元類就是 Meta,基於的是第三條規則!
元類怎麼用
和 type 一樣,其實我們剛才也看到了,元類定義的時候通常傳遞三個引數,分別是:
- 類名
- 從基類繼承資料的元素
- 屬性字典
這裡再舉個很簡單的例子:
都不用建立例項,只需要定義一個類,我們就可以看到一些輸出:
這就是元類,可以發現元類是傳遞了三個引數,分別是:類名/基類列表和屬性字典。
元類實戰
那麼,元類到底有什麼用呢?用處其實有很多,我就不自己寫例項了,不然可能就會脫離實際,讓大家說沒有意義,要就來個實際的應用,就以 Flask 為例吧,看下 Flask 裡面是如何應用 元類 的,我看的是 Flask 0.12.2 版本,這個版本里面只用了一處的 元類,那就是 View 類裡面,程式碼為:
這裡的用法比較奇特,它並沒有用到我們上面提到的兩種方法中的任何一種,反而是在 Line 9 中使用 type.new,構建了一個例項作為 MethodView
的父類,這種方法在參考資料 [5] 中作了詳細介紹。之所以用這種方式,是因為這種方式更加 OOP,因為我們可以在之前的例子裡面看到:
class MyClass(metaclass=Meta)
一點也不 OOP,因為無論是在 Java 中還是在 C++ 中,好像都沒有說繼承列表裡面帶引數名的吧?
Reference
相關文章
- 淺析 Python 的類、繼承和多型Python繼承多型
- PHP Clourse(閉包類) 淺析PHP
- Python yield 使用淺析Python
- python的metaclass淺析Python
- Java類的生命週期淺析Java
- 【轉】Python yield 使用淺析Python
- Python 元類Python
- es6類的繼承淺析繼承
- 淺析 Bootstrap 的 CSS 類名設計bootCSS
- 淺析Java語言中的內部類Java
- 用Python淺析股票資料Python
- Python wsgiref 模組原始碼淺析Python原始碼
- 【python】if __name__ == '__main__' 淺析PythonAI
- Java8 Lambda表示式、Optional類淺析Java
- Python的元類Python
- 【Python】傳送郵件功能淺析Python
- Python元類與列舉類Python
- Java&Android開發-淺析ServiceLoader類JavaAndroid
- iOS Block淺淺析iOSBloC
- [心得]python元類解密Python解密
- Python元類再談Python
- 淺析Python專案伺服器部署Python伺服器
- 淺析 JWTJWT
- MongoDB淺析MongoDB
- RunLoop 淺析OOP
- Nginx淺析Nginx
- 淺析 requestAnimationFramerequestAnimationFrame
- 淺析PromisePromise
- 淺析GitGit
- 淺析RedisRedis
- Jvm 淺析JVM
- 由ORM談Python元類ORMPython
- Python之元類筆記Python筆記
- python中的元類MetaclassPython
- 草根學Python(十二)元類Python
- 理解Python中的元類Python
- 淺析常用的Python Web的幾大框架PythonWeb框架
- Webpack 原理淺析Web