实例,我从这里的信息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