6

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 class to A.

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

1
  • What is the reason for doing this?
    – S.Lott
    Commented Mar 6, 2009 at 14:22

3 Answers 3

5

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

1

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.

1

A metaclass is the class of a class. IMO, the bloke here covered it quite serviceably, including some use-cases. See Stack Overflow question "MetaClass", "new", "cls" and "super" - what is the mechanism exactly?.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.