Python如何定義有可選引數的元類
問題
你想定義一個元類,允許類定義時提供可選引數,這樣可以控制或配置型別的建立過程。
解決方案
在定義類的時候,Python允許我們使用 ``metaclass``關鍵字引數來指定特定的元類。 例如使用抽象基類:
from abc import ABCMeta,abstractmethod class IStream(metaclass=ABCMeta): @abstractmethod def read(self,maxsize=None): pass @abstractmethod def write(self,data): pass
然而,在自定義元類中我們還可以提供其他的關鍵字引數,如下所示:
class Spam(metaclass=MyMeta,debug=True,synchronize=True): pass
為了使元類支援這些關鍵字引數,你必須確保在 __prepare__()
,__new__()
和 __init__()
方法中 都使用強制關鍵字引數。就像下面這樣:
class MyMeta(type): # Optional @classmethod def __prepare__(cls,name,bases,*,debug=False,synchronize=False): # Custom processing pass return super().__prepare__(name,bases) # Required def __new__(cls,ns,synchronize=False): # Custom processing pass return super().__new__(cls,ns) # Required def __init__(self,synchronize=False): # Custom processing pass super().__init__(name,ns)
討論
給一個元類新增可選關鍵字引數需要你完全弄懂類建立的所有步驟, 因為這些引數會被傳遞給每一個相關的方法。 __prepare__()
方法在所有類定義開始執行前首先被呼叫,用來建立類名稱空間。 通常來講,這個方法只是簡單的返回一個字典或其他對映物件。 __new__()
方法被用來例項化最終的類物件。它在類的主體被執行完後開始執行。 __init__()
方法最後被呼叫,用來執行其他的一些初始化工作。
當我們構造元類的時候,通常只需要定義一個 __new__()
或 __init__()
方法,但不是兩個都定義。 但是,如果需要接受其他的關鍵字引數的話,這兩個方法就要同時提供,並且都要提供對應的引數簽名。 預設的 __prepare__()
__prepare__()
方法。
通過使用強制關鍵字引數,在類的建立過程中我們必須通過關鍵字來指定這些引數。
使用關鍵字引數配置一個元類還可以視作對類變數的一種替代方式。例如:
class Spam(metaclass=MyMeta): debug = True synchronize = True pass
將這些屬性定義為引數的好處在於它們不會汙染類的名稱空間, 這些屬性僅僅只從屬於類的建立階段,而不是類中的語句執行階段。 另外,它們在 __prepare__()
方法中是可以被訪問的,因為這個方法會在所有類主體執行前被執行。 但是類變數只能在元類的 __new__()
和 __init__()
方法中可見。
以上就是Python如何定義有可選引數的元類的詳細內容,更多關於Python定義元類的資料請關注我們其它相關文章!