如果希望創建某一批類全部具有某種特征,則可通過 metaclass 來實現。使用 metaclass 可以在創建類時動態修改類定義。
為了使用 metaclass 動態修改類定義,程序需要先定義 metaclass, metaclass 應該繼承 type 類,並重寫 __new__() 方法。
下面程序定義了一個 metaclass 類:
#定義ItemMetaClass,繼承type class ItemMetaClass(type): # cls 代表動態修改的類 # name 代表動態修改的類名 # bases 代表被動態修改的類的所有父類 # attrs 代表被動態修改的類的所有屬性、方法組成的字典 def __new__(cls, name, bases, attrs): #動態為該類添加一個cal_price方法 attrs['cal_price'] = lambda self:self.price * self._discount return type.__new__(cls, name, bases, attrs)
上面程序定義了一個 ItemMetaClass 類,該類繼承了 type 類,並重寫了 __new__ 方法,在重寫該方法時為目標類動態添加了一個 cal_price 方法。
metaclass 類的 __new__ 方法的作用是:當程序使用 class 定義新類時,如果指定了 metaclass,那么 metaclass 的 __new__ 方法就會被自動執行。
例如,如下程序使用 metaclass 定義了兩個類:
#定義book類 class Book(metaclass=ItemMetaClass): __slots__ = ('name', 'price', '_discount') def __init__(self, name, price): self.name = name self.price = price @property def discount(self): return self._discount @discount.setter def discount(self, discount): self._discount = discount #定義cellPhone類 class CellPhone(metaclass=ItemMetaClass): __slots__ = ('price', '_discount') def __init__(self, price): self.price = price @property def discount(self): return self._discount @discount.setter def discount(self, discount): self._discount = discount
上面程序定義了 Book 和 CellPhone 兩個類,在定義這兩個類時都指定了 metaclass 信息,因此當 Python 解釋器在創建這兩個類時,ItemMetaClass 的 __new__ 方法就會被調用,用於修改這兩個類。
ItemMetaClass 類的 __new__ 方法會為目標類動態添加 cal_price 方法,因此,雖然在定義 Book、CellPhone 類時沒有定義 cal_price() 方法,但這兩個類依然有 cal_price() 方法。如下程序測試了 Book、CellPhone 兩個類的 cal_price() 方法:
#Book類實例化 b = Book('Python基礎教程', 89) b.discount = 0.8 #Book類的cal_price()方法 print(b.cal_price()) #CellPhone類實例化 cp = CellPhone(2300) cp.discount = 0.85 #CellPhone類的cel_price方法 print(cp.cal_price())
輸出結果如下:
71.2 1955.0