Python深入淺出分析元類
一、類和對象
Python屬於動態類型的語言,而動態語言和靜態語言最大的不同,就是函數和類的定義,不是編譯時創建的,而是運行時動態創建的,比方說我們要定義一個 Person
的class,就寫一個 Person.py
模塊:
# -*- coding: utf-8 -*- # 文件名 : Person.py class Person(object): def say(self, s='元類'): print('今日學習:%s' % s) if __name__ == '__main__': p = Person() p.say()
當Python解釋器載入 Person
模塊時,就會依次執行該模塊的所有語句,執行結果就是動態創建出一個 Person
的class對象,測試如下,(註意,是引入一個Person.py腳本)
# 文件名 :測試.py # 引入模塊,需要模塊的路徑 from Person import Person # 創建一個Person類的實例 p = Person() p.say('Python中的元類') # 調用say方法 # 今日學習:Python中的元類 print(type(p)) # 把實例 p 的類型打印出來 # <class 'say.Person'> print(type(Person)) # Person 類的類型打印出來 # <class 'type'>
這裡是用來 type()
函數,可以查看一個類型或變量,的類型, Person
是一個class,它的類型就是 type
,而 p
是一個實例,它的類型就是class Person
。
二、type類
我們說class的定義是運行時動態創建的,而創建class的方法就是使用 type()
函數
type()
函數既可以返回一個對象的類型,又可以創建出新的類型,比如,我們可以通過 type()
函數創建出Person 類,而無需通過 class Person(object)...
的定義,此時type的第二種用法,我們隻要type傳object是可以返回該對象類型的,但是當我們的type存在三位參數存在時
# type 類 class type(object): """ type(object_or_name, bases, dict) type(object) -> the object's type type(name, bases, dict) -> a new type """ #參數介紹 """ type(object_or_name, bases, dict) object-or-name -- 對象或類的名稱。 bases -- 基類的元組。 dict -- 字典,類內定義的命名空間變量。 """ # 返回新的類型對象。
# -*- coding: utf-8 -*- def fun(self, s): print('hello'+s) Hello = type('hello', (object,), dict(func=fun)) if __name__ == '__main__': h = Hello() h.func(' word') # hello word print(type(h)) # <class '__main__.hello'> print(type(Hello)) # <class 'type'>
我們通過 type()
函數創建的類和直接寫class是完全一樣的,因為Python解釋器遇到class定義時,僅僅是掃描一下class定義的語法,然後調用 type()
函數創建出class
在正常情況下,我們都用 class Xxx...
來定義類,但是, type()
函數也允許我們動態創建出類來,也就是說,動態語言本身支持運行期動態創建類,這和靜態語言有非常大的不同,要在靜態語言運行期創建類,必須構造源代碼字符串再調用編譯器,或者借助一些工具生成字節碼實現,本質上都是動態編譯,會非常復雜
三、元類Metaclass
除瞭使用 type()
動態創建類以外,要控制類的創建行為,還可以使用metaclass
,也就是元類
當我們定義瞭類以後,就可以根據這個類創建出實例,所以:先定義類,然後創建實例
但是如果我們想創建出類呢?那就必須根據metaclass創建出類,所以:先定義metaclass
,然後創建類,元類就是用來創建這些類(對象)的,元類就是類的類
我們先看一個簡單的例子,這個metaclass
可以給自定義的類增加一個 add
方法定義 ListMetaclass
,按照默認習慣,metaclass的類名總是以Metaclass結尾,以便清楚地表示這是一個metaclas。
四、自定義一個元類
class UpperMetaclass(type): def __new__(mcs, class_name, class_parents, class_attrs): new_attrs = {} for name, value in class_attrs.items(): if not name.startswith('__'): # 判斷是否為非私有屬性 new_attrs[name.upper()] = value # 直接調用type 來創建一個類 return type.__new__(mcs, class_name, class_parents, class_attrs) # 測試 class Emp(object, metaclass=UpperMetaclass): name = '張三' acl = 500 if __name__ == '__main__': print(hasattr(Emp, 'name')) # 判斷Emp中是否有名字為name print(hasattr(Emp, 'NAME')) # 判斷Emp中是否有名字為NAME
到此這篇關於Python深入淺出分析元類的文章就介紹到這瞭,更多相關Python元類內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- python中的type,元類,類,對象用法
- 關於Python 多重繼承時metaclass conflict問題解決與原理探究
- python中的元類metaclass詳情
- Python黑魔法之metaclass詳情
- Python基礎之元編程知識總結