實例,我從這裏的信息riffing:Metaclass not being called in subclasses蟒蛇3.2插件廠:從類/元類
我的問題是,我無法創建一個使用這個類註冊表中的對象的實例。如果我使用「常規」構造方法,那麼它似乎正確地實例化對象;但是當我嘗試使用與註冊表關聯的類對象時,那麼我得到一個錯誤,我傳遞的參數數量不正確。 (似乎是調用元類新而不是我的構造函數...... ??)
我不清楚它爲什麼失敗,因爲我認爲我應該能夠通過使用類對象創建一個實例「可調用」語法。
似乎我得到的元類放在註冊表中,而不是類本身?但我沒有看到在新的調用中訪問類本身的簡單方法。
這裏是我的代碼示例,從而未能實例化一個變量「d」:
registry = [] # list of subclasses class PluginMetaclass(type): def __new__(cls, name, bases, attrs): print(cls) print(name) registry.append((name, cls)) return super(PluginMetaclass, cls).__new__(cls, name, bases, attrs) class Plugin(metaclass=PluginMetaclass): def __init__(self, stuff): self.stuff = stuff # in your plugin modules class SpamPlugin(Plugin): def __init__(self, stuff): self.stuff = stuff class BaconPlugin(Plugin): def __init__(self, stuff): self.stuff = stuff c = SpamPlugin(0) b = BaconPlugin(0) mycls = registry[1][1] d = mycls(0)
感謝您的幫助。
是的,Greg,謝謝。我猜昨天測試了幾個小時,然後發生在一個更簡單的解決方案上。將__new__替換爲__init__,第一個參數是類名,而不是元類名。對super .__ init__的調用將需要刪除第一個參數,否則它是對原始代碼的修復,只涉及將__new__更改爲__init__。我當然希望文檔在metaclasses的可用接口上更加清晰。 – drone115b 2011-05-10 12:36:27
我也應該說,我有一個輕微的個人喜好使用init而不是新的。 Init是一個驗證,而新的是一個分配。我不想在低於必要的細節水平上搞亂,我認爲課堂註冊更像是一個驗證步驟。但無論哪種方式肯定有效。 – drone115b 2011-05-10 12:50:28
我同意,'__init__'對我來說也更好,對於這個應用程序肯定更合適。我認爲對'__new__'的需求在一般情況下是非常少見的,特別是對於元類來說尤其少見。 – 2011-05-10 14:06:38