Python metaclass as class factory
Table of Contents
Metaclasses are deeper magic that 99% of users should never worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).
Python Guru Tim Peters
Python rightfully prides itself as a relatively straightforward language without a lot of "magic" hiding in its workings and features. Sometimes, however, to make interesting abstractions possible, one can dig deep in Python's more dusty and obscure corners to find language constructs that are a bit more magical than usual. Metaclasses are one such feature.
A metaclass is most commonly used as a class-factory.
Classes are obects too
And it is possible to generate them on the fly:
def make_sample_class(**kw): return type('DemoClass', (object,), dict(**kw))
type produce a
DemoClass blueprint. Lets
compose the class itself:
sample_class = make_sample_class(a=1, b=2) print(type(sample_class))
And now it is time to generate a particular instance:
instance = sample_class() print(type(instance)) print("This is an instance's properties a: %s and b: %s " % (instance.a, instance.b))
<class '__main__.DemoClass'> ... This is an instance's properties a: 1 and b: 2
The class of a class
Every object (including built-ins) in Python has a class. We've just seen that classes are objects too, so classes must also have a class, right? Exactly. Python lets us examine the class of an object with the class attribute. Let's see this in action:
class SampleClass(object): pass sample_object = SampleClass() sample_object.__class__ SampleClass.__class__
>>> >>> <class '__main__.SampleClass'> <class 'type'>
A metaclass is defined as "the class of a class". Any class whose instances are themselves classes, is a metaclass. So, according to what we've seen above, this makes
typea metaclass - in fact, the most commonly used metaclass in Python, since it's the default metaclass of all classes.
class Meta(object): meta_variable = 'zero' class ExtClass(object): __metaclass__ = Meta ext_variable = 'infinity' print(ExtClass.__metaclass__) dumb_objext = ExtClass() print(dumb_objext.ext_variable) print(dumb_objext.__metaclass__.meta_variable)
... >>> ... ... ... >>> >>> <class '__main__.Meta'> >>> infinity zero
Metaclass's new and init
blog comments powered by Disqus