HomePython Page 5 - Metaclasses: Blueprints of Blueprints
A class named G - Python
We all know that objects are created from classes. But can a class be created from a class? Yes it can; this is called a metaclass. They give us a great deal of power when it comes to changing the behavior of a class. Python 2.2 supports metaclasses. Peyton McCullough explains.
What if we wanted to return a “map” of a class' attributes? We would need to loop through the attribute dictionary and format the contents. Instead of redoing the __str__ method, though, we will redo __repr__. This way, the contents of an instance can be spilled out in the command line by just typing the instance class' name, rather than attaching print. MetaH does all of this for us:
>>> import types >>> class MetaH ( type ):
# Create a dictionary variable to store the attributes in # We want to use the attribute dictionary in __repr__ dct = None
# Create another to store variables in variables = []
# Loop through the attributes and add them for key, value in cls.dct.iteritems(): if type ( value ) == types.FunctionType: methods.append ( key ) else: variables.append ( key )
# Sort the lists methods.sort() variables.sort()
# Create a string to store the "map" in map = "Class Map"
# Put everything in the map map = map + "\n\nMETHODS:" for method in methods: map = map + "\n" + method map = map + "\n\nVARIABLES:" for variable in variables: map = map + "\n" + variable
# Return the map return map
The first thing that MetaH does is create a variable to house the dictionary of attributes. The dictionary of attributes is moved to the variable in the __init__ method. We then create lists to store the class' methods and variables in the __repr__ method, and we loop through the dictionary to see what attribute belongs where. Finally, we sort the lists, create a string and then return that string. Here's our metaclass in action:
>>> class H ( object ): __metaclass__ = MetaH a = 1 b = 2 c = 3 def d ( self ): pass def e ( self ): pass def f ( self ): pass
>>> H Class Map
METHODS: d e f
VARIABLES: __metaclass__ __module__ a b c
Wrapping It Up
You should now know what metaclasses are and should have an idea of what situations call for the use of metaclasses. Metaclasses are, in the simplest definition, blueprints of blueprints. The relationship between a metaclass and a class is just like the relationship between a class and an object. A class changes the behavior of an object, and a metaclass changes the behavior of a class.
Although metaclasses are not used very often, they are powerful devices when they are used. They can change the internals of a class, affecting its behavior in ways not normally possible. They can also be used to generate classes dynamically, just as objects can be created dynamically from classes.