我一直在使用Python破解类:
def hack(f,aClass) :
class MyClass(aClass) :
def f(self) :
f()
return MyClass
A = hack(afunc,A)
对我来说这看起来很干净。它需要一个类,A,创建一个派生自它的新类,它有一个额外的方法,调用f,然后将新类重新分配给A.
这与Python中的元类黑客有何不同?使用元类对此有什么好处?
答案 0 :(得分:5)
Python中类的定义是类型的实例(或类型的子类的实例)。换句话说,类定义本身就是一个对象。使用元类,您可以控制成为类定义的类型实例。
调用元类时,您可以完全重写类定义。您可以访问类的所有建议属性,它的祖先等。不仅仅是注入方法或删除方法,您可以从根本上改变继承树,类型以及几乎任何其他方面。您还可以将元类链接在一起,以获得非常动态且完全错综复杂的体验。
我认为真正的好处是,类的类型仍然是类的类型。在您的示例中,键入:
a_inst = A()
type(a_inst)
将显示它是MyClass
的实例。是的,isinstance(a_inst, aClass)
将返回True
,但您引入了一个子类,而不是动态重新定义的类。区别可能是关键。
正如rjh指出的那样,匿名内部类也具有性能和可扩展性含义。元类只处理一次,并且是定义类的时刻,而不是再次处理。 API的用户也可以扩展您的元类,因为它没有包含在函数中,因此您可以获得一定程度的可扩展性。
这篇稍微陈旧的文章实际上有一个很好的解释,它将您在示例中使用的“函数修饰”方法与元类完全比较,并在该上下文中显示Python元类演变的历史记录:http://www.ibm.com/developerworks/linux/library/l-pymeta.html
答案 1 :(得分:1)
元类是类的类。 IMO,这里的家伙非常有用,包括一些用例。请参阅Stack Overflow问题 "MetaClass", "new", "cls" and "super" - what is the mechanism exactly? 。
答案 2 :(得分:1)
您也可以使用type
callable。
def hack(f, aClass):
newfunc = lambda self: f()
return type('MyClass', (aClass,), {'f': newfunc})
我发现使用type
进入元类世界的最简单方法。