元類
1、什么是元類
創建出類的類,就是元類,例如:type就是元類
2、如何產生類
產生類的方法有兩種:
第一種:通過class關鍵字產生類
# 1.通過class關鍵字產生類 class Chinese(object): country = 'China' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex p_obj = Chinese("張三", 87, "male") print(type(p_obj)) # <class '__main__.Chinese'> # 類本質上也是一個物件,因為在python中 一切皆物件 print(Chinese) # <class '__main__.Chinese'>
第二種:通過type產生類 type()
# 2.通過呼叫type產生類:type() code = """ country = 'China' def __init__(self, name, age, sex): self.name = name self.age = age self.sex = sex """ class_attr = {} # 定義一個類的名稱空間class_attr # exec()是python的內置函式,可以將字串的代碼添加到名稱空間中,名稱空間可以自定義; # 語法exec(字串形式的代碼,全域名稱空間,區域名稱空間) exec(code, {}, class_attr) # 將code中的代碼添加到全域和區域名稱空間中
# type()需要傳入的引數:what, bases=None, dict=None # what:在這里指的是類名 bases:繼承的父類,也就是基類 dict:類的名稱空間 obj = type("Chinese", (object, ), class_attr) # 產生一個Chinese類的物件obj print(obj) # <class '__main__.Chinese'>
3、元類的作用
元類可以控制類的創建程序
例:
先創建一個元類,然后要求根據元類創建的類的類名字必須首字母大寫而且類內部必須要有注釋
# 自定義一個元類, 元類在此是“控制類” class MyMetaClass(type): # 繼承type類,然后重寫type類中的方法來創建類 # 重寫type類的__init__方法 # 將type()中需要傳入的三個引數:what, bases=None, dict=None 改為 class_name, class_bases, class_dict (這里僅僅只是改了個名字而已) def __init__(self, class_name, class_bases, class_dict): # print(class_name) # print(class_bases) # print(class_dict) if not class_name.istitle(): # .istitle():判斷首字母是否是大寫 raise NameError("類的名字首字母必須大寫!!!") # 拋出例外 if not class_dict.get("__doc__"): # 判斷類的名稱空間中是否有__doc__屬性,即“注釋” raise TypeError("類必須寫注釋!!!") # 拋出例外 # 必須將類中的類名、類的基類、類的名稱空間,一并回傳給type中的__init__ super().__init__(class_name, class_bases, class_dict) # 以下為呼叫類時,類內部如何產生空物件以及物件名稱空間的原理(不必懂): # __call__控制呼叫類的行為 # 呼叫類時type內部一定會呼叫一次__call__,由__call__來幫你呼叫__new__創建空物件,然后__call__再呼叫__init__將類中傳入的引數放入物件的名稱空間中 def __call__(self, *args, **kwargs): # 重寫type類的__call__方法 print(args) # 列印的args為呼叫類傳入的引數 # 呼叫object來創建一個空物件obj obj = object.__new__(self) # 呼叫類時,__call__會立馬呼叫 類名.__init__,并且將obj連同User括號內的引數一同傳給__init__,然后產生名稱空間 self.__init__(obj, *args, **kwargs) return obj
# 自定義一個類,此類在此時是新創建的MyMetaClass元類的被控制類 # 被控制類在定義階段的 "metaclass=自定義的元類"引數,他會將當前被控制類的名稱、類的基類、類的名稱空間一并傳給自定義的元類(上面創建的MyMetaClass元類) # metaclass=自定義的元類,自定義的元類繼承了type元類,那么他就會去呼叫type元類(名稱、類的基類、類的名稱空間) class User(object, metaclass=MyMetaClass): # 被控制類,MyMetaClass(User, (object, ), {"x": 10}) """y is very handsome~""" x = 10 pass
# obj = User() # 此處呼叫被控制類不傳參,所以上面列印出的args引數為空,即 ()
此例的需求是:控制創建類的類名字必須首字母大寫而且類內部必須要有注釋,下面開始演示(上面為按照元類的需求來寫,下面開始演示不按照需求來寫)
演示一:被控制類名字首字母小寫

執行結果:

演示二:被控制類中不寫注釋

執行結果:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/215641.html
標籤:其他
