6

我一直在像这样在 Python 中编写类:

def hack(f,aClass) :
  class MyClass(aClass) :
     def f(self) :
       f()
  return MyClass

A = hack(afunc,A)

这对我来说看起来很干净。它接受一个类 A,创建一个从它派生的具有额外方法的新类,调用 f,然后将新类重新分配给 A。

这与 Python 中的元类黑客攻击有何不同?与此相比,使用元类有什么优势?

4

3 回答 3

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

于 2009-03-06T14:27:36.283 回答
1

元类是类的类。IMO,这里的家伙很好地覆盖了它,包括一些用例。请参阅 Stack Overflow 问题“MetaClass”、“ new ”、“cls”和“super”——具体的机制是什么?.

于 2009-05-03T00:09:30.353 回答
1

您也可以使用type可调用对象。

def hack(f, aClass):
    newfunc = lambda self: f()
    return type('MyClass', (aClass,), {'f': newfunc})

我发现使用type最简单的方法进入元类世界。

于 2009-05-27T06:40:19.413 回答