In object-oriented programming, a metaclass is a class whose instances are classes. Just as an ordinary class defines the behavior of certain objects, a metaclass defines the behavior of certain classes and their instances.
In Python, the builtin class type is a metaclass. Consider this simple Python class:
class Car(object): __slots__ = 'model', 'year', 'color' def __init__(self, make, model, year, color): self.make = make self.model = model self.year = year self.color = color @property def description(self): """ Return a description of this car. """ return "%s %s %s %s" % (self.color, self.year, self.make, self.model)
At run time, Car itself is a type object. The source code of the Car class, shown above, does not include such details as the size in bytes of Car objects, their binary layout in memory, how they are allocated, that the __init__ method is automatically called each time a Car is created, and so on. These details come into play not only when a new Car object is created, but also each time any attribute of a Car is accessed. In languages without metaclasses, such as Java, these details are defined by the language specification and can't be overridden. In Python, the metaclass, type, controls these details of Car's behavior. They can be overridden by using a different metaclass instead of type.
The above example contains some redundant code to do with the four attributes make, model, year, and color. It is possible to eliminate some of this redundancy using a metaclass. In Python, a metaclass is most easily defined as a subclass of type.
class AttributeInitType(type): def __call__(self, *args, **kwargs): """ Create a new instance. """ # First, create the object in the normal default way. obj = type.__call__(self, *args) # Additionally, set attributes on the new object. for name in kwargs: setattr(obj, name, kwargs*) # Return the new object. return obj
This metaclass only overrides object creation. All other aspects of class and object behavior are still handled by type.
Now the class Car can be rewritten to use this metaclass. This is done by assigning to __metaclass__ within the class definition:
class Car(object): __metaclass__ = AttributeInitType __slots__ = 'model', 'year', 'color' @property def description(self): """ Return a description of this car. """ return "%s %s %s %s" % (self.color, self.year, self.make, self.model)
Car objects can then be instantiated like this:
cars = [ Car(make='Toyota', model='Prius', year=2005, color='green'), Car(make='Ford', model='Prefect', year=1979, color='blue')]
Metaprogramming can be confusing, and it is rare in real-world Python code.
The following programming tools support metaclasses.
This article is licensed under the GNU Free Documentation License.
It uses material from the
"Metaclass".
Home Page • arts • business • computers • games • health • hospitals • home • kids & teens • news • physicians • recreation• reference • regional • science • shopping • society • sports • world