views:

693

answers:

3
+2  Q: 

Python metaclasses

I've been hacking classes in python like this :

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

A = hack(afunc,A)

Which looks pretty clean to me. It takes a class A, creates a new class derived from it, that has an extra method, calling f, and then reassigns the new clas to A.

How does this differ from metaclass hacking in Python. What are the advantages of using metaclass over this?

+3  A: 

The definition of a class in python is an instance of type (or an instance of a subclass of type). In other words, the class definition itself is an object. With metaclasses, you have the ability to control the type instance that becomes the class definition.

When a metaclass is invoked, you have the ability to completely re-write the class definition. You have access to all the proposed attributes of the class, its ancestors, etc. More than just injecting a method or removing a method, you can radically alter the inheritance tree, the type, and pretty much any other aspect. You can also chain metaclasses together for a very dynamic and totally convoluted experience.

I suppose the real benefit, though is that the class's type remains the class's type. In your example, typing:

a_inst = A()
type(a_inst)

will show that it is an instance of MyClass. Yes, isinstance(a_inst, aClass) would return True, but you've introduced a subclass, rather than a dynamically re-defined class. The distinction there is probably the key.

As rjh points out, the anonymous inner class also has performance and extensibility implications. A metaclass is processed only once, and the moment that the class is defined, and never again. Users of your API can also extend your metaclass because it is not enclosed within a function, so you gain a certain degree of extensibility.

This slightly old article actually has a good explanation that compares exactly the "function decoration" approach you used in the example with metaclasses, and shows the history of the Python metaclass evolution in that context: http://www.ibm.com/developerworks/linux/library/l-pymeta.html

Jarret Hardie
A: 

A metaclass is the class of a class. IMO, the bloke here covered it quite serviceably, including some use-cases:

http://stackoverflow.com/questions/395982/metaclass-new-cls-and-super-can-someone-explain-the-mechanism-exactly/396109#396109

David Alan
A: 

You can use the type callable as well.

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

I find using type the easiest way to get into the metaclass world.

Antti Rasinen