Metaclasses seem to be an obscure, misunderstood area of Python’s object model. Here is a simple example that I’ve used to both understand and explain what metaclasses are, and how they can be used.
This code snippet was spawned from a colleague’s query.
"What would be the most pythonic way to override a class type’s string representation?"
Expressed in code, he wanted a new-style class type A to behave like
>>> A <class '__main__.A'> >>> str(A) 'Hello World'
Unfotunately, overriding A’s __str__
method
>>> class A(object): ... def __str__(self): ... return "Hello World" ... >>> A <class '__main__.A'> >>> str(A) "<class '__main__.A'>" >>> str(A()) 'Hello World' >>>
only overrides the string representation of instances of A, rather than type A.
Metaclasses are the solution to this dilemma. My colleague’s conundrum can be solved by creating a new-style class with base type
and a __str__
method. This acts to override the __str__
method of A’s type rather than instances of A.
>>> class meta_A(type): ... def __str__(cls): ... return "Hello World" ... >>> class A(object): ... __metaclass__ = meta_A ... >>> A <class '__main__.A'> >>> str(A) 'Hello World' >>> str(A()) '<__main__.A object at 0x10049e710>'
Thus, we have a pythonic mechanism for overriding the string representation of any class type.
Note that there is new syntax in Python 3+ for specifying a metaclass.
>>> class A(metaclass=meta_A): ... pass ...