What are metaclasses in Python?

Viewed 1046461

What are metaclasses? What are they used for?

24 Answers

A metaclass is the class of a class. A class defines how an instance of the class (i.e. an object) behaves while a metaclass defines how a class behaves. A class is an instance of a metaclass.

While in Python you can use arbitrary callables for metaclasses (like Jerub shows), the better approach is to make it an actual class itself. type is the usual metaclass in Python. type is itself a class, and it is its own type. You won't be able to recreate something like type purely in Python, but Python cheats a little. To create your own metaclass in Python you really just want to subclass type.

A metaclass is most commonly used as a class-factory. When you create an object by calling the class, Python creates a new class (when it executes the 'class' statement) by calling the metaclass. Combined with the normal __init__ and __new__ methods, metaclasses therefore allow you to do 'extra things' when creating a class, like registering the new class with some registry or replace the class with something else entirely.

When the class statement is executed, Python first executes the body of the class statement as a normal block of code. The resulting namespace (a dict) holds the attributes of the class-to-be. The metaclass is determined by looking at the baseclasses of the class-to-be (metaclasses are inherited), at the __metaclass__ attribute of the class-to-be (if any) or the __metaclass__ global variable. The metaclass is then called with the name, bases and attributes of the class to instantiate it.

However, metaclasses actually define the type of a class, not just a factory for it, so you can do much more with them. You can, for instance, define normal methods on the metaclass. These metaclass-methods are like classmethods in that they can be called on the class without an instance, but they are also not like classmethods in that they cannot be called on an instance of the class. type.__subclasses__() is an example of a method on the type metaclass. You can also define the normal 'magic' methods, like __add__, __iter__ and __getattr__, to implement or change how the class behaves.

Here's an aggregated example of the bits and pieces:

def make_hook(f):
    """Decorator to turn 'foo' method into '__foo__'"""
    f.is_hook = 1
    return f

class MyType(type):
    def __new__(mcls, name, bases, attrs):

        if name.startswith('None'):
            return None

        # Go over attributes and see if they should be renamed.
        newattrs = {}
        for attrname, attrvalue in attrs.iteritems():
            if getattr(attrvalue, 'is_hook', 0):
                newattrs['__%s__' % attrname] = attrvalue
            else:
                newattrs[attrname] = attrvalue

        return super(MyType, mcls).__new__(mcls, name, bases, newattrs)

    def __init__(self, name, bases, attrs):
        super(MyType, self).__init__(name, bases, attrs)

        # classregistry.register(self, self.interfaces)
        print "Would register class %s now." % self

    def __add__(self, other):
        class AutoClass(self, other):
            pass
        return AutoClass
        # Alternatively, to autogenerate the classname as well as the class:
        # return type(self.__name__ + other.__name__, (self, other), {})

    def unregister(self):
        # classregistry.unregister(self)
        print "Would unregister class %s now." % self

class MyObject:
    __metaclass__ = MyType


class NoneSample(MyObject):
    pass

# Will print "NoneType None"
print type(NoneSample), repr(NoneSample)

class Example(MyObject):
    def __init__(self, value):
        self.value = value
    @make_hook
    def add(self, other):
        return self.__class__(self.value + other.value)

# Will unregister the class
Example.unregister()

inst = Example(10)
# Will fail with an AttributeError
#inst.unregister()

print inst + inst
class Sibling(MyObject):
    pass

ExampleSibling = Example + Sibling
# ExampleSibling is now a subclass of both Example and Sibling (with no
# content of its own) although it will believe it's called 'AutoClass'
print ExampleSibling
print ExampleSibling.__mro__

Note, this answer is for Python 2.x as it was written in 2008, metaclasses are slightly different in 3.x.

Metaclasses are the secret sauce that make 'class' work. The default metaclass for a new style object is called 'type'.

class type(object)
  |  type(object) -> the object's type
  |  type(name, bases, dict) -> a new type

Metaclasses take 3 args. 'name', 'bases' and 'dict'

Here is where the secret starts. Look for where name, bases and the dict come from in this example class definition.

class ThisIsTheName(Bases, Are, Here):
    All_the_code_here
    def doesIs(create, a):
        dict

Lets define a metaclass that will demonstrate how 'class:' calls it.

def test_metaclass(name, bases, dict):
    print 'The Class Name is', name
    print 'The Class Bases are', bases
    print 'The dict has', len(dict), 'elems, the keys are', dict.keys()

    return "yellow"

class TestName(object, None, int, 1):
    __metaclass__ = test_metaclass
    foo = 1
    def baz(self, arr):
        pass

print 'TestName = ', repr(TestName)

# output => 
The Class Name is TestName
The Class Bases are (<type 'object'>, None, <type 'int'>, 1)
The dict has 4 elems, the keys are ['baz', '__module__', 'foo', '__metaclass__']
TestName =  'yellow'

And now, an example that actually means something, this will automatically make the variables in the list "attributes" set on the class, and set to None.

def init_attributes(name, bases, dict):
    if 'attributes' in dict:
        for attr in dict['attributes']:
            dict[attr] = None

    return type(name, bases, dict)

class Initialised(object):
    __metaclass__ = init_attributes
    attributes = ['foo', 'bar', 'baz']

print 'foo =>', Initialised.foo
# output=>
foo => None

Note that the magic behaviour that Initialised gains by having the metaclass init_attributes is not passed onto a subclass of Initialised.

Here is an even more concrete example, showing how you can subclass 'type' to make a metaclass that performs an action when the class is created. This is quite tricky:

class MetaSingleton(type):
    instance = None
    def __call__(cls, *args, **kw):
        if cls.instance is None:
            cls.instance = super(MetaSingleton, cls).__call__(*args, **kw)
        return cls.instance

class Foo(object):
    __metaclass__ = MetaSingleton

a = Foo()
b = Foo()
assert a is b

One use for metaclasses is adding new properties and methods to an instance automatically.

For example, if you look at Django models, their definition looks a bit confusing. It looks as if you are only defining class properties:

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

However, at runtime the Person objects are filled with all sorts of useful methods. See the source for some amazing metaclassery.

I think the ONLamp introduction to metaclass programming is well written and gives a really good introduction to the topic despite being several years old already.

http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html (archived at https://web.archive.org/web/20080206005253/http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html)

In short: A class is a blueprint for the creation of an instance, a metaclass is a blueprint for the creation of a class. It can be easily seen that in Python classes need to be first-class objects too to enable this behavior.

I've never written one myself, but I think one of the nicest uses of metaclasses can be seen in the Django framework. The model classes use a metaclass approach to enable a declarative style of writing new models or form classes. While the metaclass is creating the class, all members get the possibility to customize the class itself.

The thing that's left to say is: If you don't know what metaclasses are, the probability that you will not need them is 99%.

Role of a metaclass' __call__() method when creating a class instance

If you've done Python programming for more than a few months you'll eventually stumble upon code that looks like this:

# define a class
class SomeClass(object):
    # ...
    # some definition here ...
    # ...

# create an instance of it
instance = SomeClass()

# then call the object as if it's a function
result = instance('foo', 'bar')

The latter is possible when you implement the __call__() magic method on the class.

class SomeClass(object):
    # ...
    # some definition here ...
    # ...

    def __call__(self, foo, bar):
        return bar + foo

The __call__() method is invoked when an instance of a class is used as a callable. But as we've seen from previous answers a class itself is an instance of a metaclass, so when we use the class as a callable (i.e. when we create an instance of it) we're actually calling its metaclass' __call__() method. At this point most Python programmers are a bit confused because they've been told that when creating an instance like this instance = SomeClass() you're calling its __init__() method. Some who've dug a bit deeper know that before __init__() there's __new__(). Well, today another layer of truth is being revealed, before __new__() there's the metaclass' __call__().

Let's study the method call chain from specifically the perspective of creating an instance of a class.

This is a metaclass that logs exactly the moment before an instance is created and the moment it's about to return it.

class Meta_1(type):
    def __call__(cls):
        print "Meta_1.__call__() before creating an instance of ", cls
        instance = super(Meta_1, cls).__call__()
        print "Meta_1.__call__() about to return instance."
        return instance

This is a class that uses that metaclass

class Class_1(object):

    __metaclass__ = Meta_1

    def __new__(cls):
        print "Class_1.__new__() before creating an instance."
        instance = super(Class_1, cls).__new__(cls)
        print "Class_1.__new__() about to return instance."
        return instance

    def __init__(self):
        print "entering Class_1.__init__() for instance initialization."
        super(Class_1,self).__init__()
        print "exiting Class_1.__init__()."

And now let's create an instance of Class_1

instance = Class_1()
# Meta_1.__call__() before creating an instance of <class '__main__.Class_1'>.
# Class_1.__new__() before creating an instance.
# Class_1.__new__() about to return instance.
# entering Class_1.__init__() for instance initialization.
# exiting Class_1.__init__().
# Meta_1.__call__() about to return instance.

Observe that the code above doesn't actually do anything more than logging the tasks. Each method delegates the actual work to its parent's implementation, thus keeping the default behavior. Since type is Meta_1's parent class (type being the default parent metaclass) and considering the ordering sequence of the output above, we now have a clue as to what would be the pseudo implementation of type.__call__():

class type:
    def __call__(cls, *args, **kwarg):

        # ... maybe a few things done to cls here

        # then we call __new__() on the class to create an instance
        instance = cls.__new__(cls, *args, **kwargs)

        # ... maybe a few things done to the instance here

        # then we initialize the instance with its __init__() method
        instance.__init__(*args, **kwargs)

        # ... maybe a few more things done to instance here

        # then we return it
        return instance

We can see that the metaclass' __call__() method is the one that's called first. It then delegates creation of the instance to the class's __new__() method and initialization to the instance's __init__(). It's also the one that ultimately returns the instance.

From the above it stems that the metaclass' __call__() is also given the opportunity to decide whether or not a call to Class_1.__new__() or Class_1.__init__() will eventually be made. Over the course of its execution it could actually return an object that hasn't been touched by either of these methods. Take for example this approach to the singleton pattern:

class Meta_2(type):
    singletons = {}

    def __call__(cls, *args, **kwargs):
        if cls in Meta_2.singletons:
            # we return the only instance and skip a call to __new__()
            # and __init__()
            print ("{} singleton returning from Meta_2.__call__(), "
                   "skipping creation of new instance.".format(cls))
            return Meta_2.singletons[cls]

        # else if the singleton isn't present we proceed as usual
        print "Meta_2.__call__() before creating an instance."
        instance = super(Meta_2, cls).__call__(*args, **kwargs)
        Meta_2.singletons[cls] = instance
        print "Meta_2.__call__() returning new instance."
        return instance

class Class_2(object):

    __metaclass__ = Meta_2

    def __new__(cls, *args, **kwargs):
        print "Class_2.__new__() before creating instance."
        instance = super(Class_2, cls).__new__(cls)
        print "Class_2.__new__() returning instance."
        return instance

    def __init__(self, *args, **kwargs):
        print "entering Class_2.__init__() for initialization."
        super(Class_2, self).__init__()
        print "exiting Class_2.__init__()."

Let's observe what happens when repeatedly trying to create an object of type Class_2

a = Class_2()
# Meta_2.__call__() before creating an instance.
# Class_2.__new__() before creating instance.
# Class_2.__new__() returning instance.
# entering Class_2.__init__() for initialization.
# exiting Class_2.__init__().
# Meta_2.__call__() returning new instance.

b = Class_2()
# <class '__main__.Class_2'> singleton returning from Meta_2.__call__(), skipping creation of new instance.

c = Class_2()
# <class '__main__.Class_2'> singleton returning from Meta_2.__call__(), skipping creation of new instance.

a is b is c # True

The type() function can return the type of an object or create a new type,

for example, we can create a Hi class with the type() function and do not need to use this way with class Hi(object):

def func(self, name='mike'):
    print('Hi, %s.' % name)

Hi = type('Hi', (object,), dict(hi=func))
h = Hi()
h.hi()
Hi, mike.

type(Hi)
type

type(h)
__main__.Hi

In addition to using type() to create classes dynamically, you can control creation behavior of class and use metaclass.

According to the Python object model, the class is the object, so the class must be an instance of another certain class. By default, a Python class is instance of the type class. That is, type is metaclass of most of the built-in classes and metaclass of user-defined classes.

class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)

class CustomList(list, metaclass=ListMetaclass):
    pass

lst = CustomList()
lst.add('custom_list_1')
lst.add('custom_list_2')

lst
['custom_list_1', 'custom_list_2']

Magic will take effect when we passed keyword arguments in metaclass, it indicates the Python interpreter to create the CustomList through ListMetaclass. new (), at this point, we can modify the class definition, for example, and add a new method and then return the revised definition.

In addition to the published answers I can say that a metaclass defines the behaviour for a class. So, you can explicitly set your metaclass. Whenever Python gets a keyword class then it starts searching for the metaclass. If it's not found – the default metaclass type is used to create the class's object. Using the __metaclass__ attribute, you can set metaclass of your class:

class MyClass:
   __metaclass__ = type
   # write here other method
   # write here one more method

print(MyClass.__metaclass__)

It'll produce the output like this:

class 'type'

And, of course, you can create your own metaclass to define the behaviour of any class that are created using your class.

For doing that, your default metaclass type class must be inherited as this is the main metaclass:

class MyMetaClass(type):
   __metaclass__ = type
   # you can write here any behaviour you want

class MyTestClass:
   __metaclass__ = MyMetaClass

Obj = MyTestClass()
print(Obj.__metaclass__)
print(MyMetaClass.__metaclass__)

The output will be:

class '__main__.MyMetaClass'
class 'type'

Note that in python 3.6 a new dunder method __init_subclass__(cls, **kwargs) was introduced to replace a lot of common use cases for metaclasses. Is is called when a subclass of the defining class is created. See python docs.

Here's another example of what it can be used for:

  • You can use the metaclass to change the function of its instance (the class).
class MetaMemberControl(type):
    __slots__ = ()

    @classmethod
    def __prepare__(mcs, f_cls_name, f_cls_parents,  # f_cls means: future class
                    meta_args=None, meta_options=None):  # meta_args and meta_options is not necessarily needed, just so you know.
        f_cls_attr = dict()
        if not "do something or if you want to define your cool stuff of dict...":
            return dict(make_your_special_dict=None)
        else:
            return f_cls_attr

    def __new__(mcs, f_cls_name, f_cls_parents, f_cls_attr,
                meta_args=None, meta_options=None):

        original_getattr = f_cls_attr.get('__getattribute__')
        original_setattr = f_cls_attr.get('__setattr__')

        def init_getattr(self, item):
            if not item.startswith('_'):  # you can set break points at here
                alias_name = '_' + item
                if alias_name in f_cls_attr['__slots__']:
                    item = alias_name
            if original_getattr is not None:
                return original_getattr(self, item)
            else:
                return super(eval(f_cls_name), self).__getattribute__(item)

        def init_setattr(self, key, value):
            if not key.startswith('_') and ('_' + key) in f_cls_attr['__slots__']:
                raise AttributeError(f"you can't modify private members:_{key}")
            if original_setattr is not None:
                original_setattr(self, key, value)
            else:
                super(eval(f_cls_name), self).__setattr__(key, value)

        f_cls_attr['__getattribute__'] = init_getattr
        f_cls_attr['__setattr__'] = init_setattr

        cls = super().__new__(mcs, f_cls_name, f_cls_parents, f_cls_attr)
        return cls


class Human(metaclass=MetaMemberControl):
    __slots__ = ('_age', '_name')

    def __init__(self, name, age):
        self._name = name
        self._age = age

    def __getattribute__(self, item):
        """
        is just for IDE recognize.
        """
        return super().__getattribute__(item)

    """ with MetaMemberControl then you don't have to write as following
    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age
    """


def test_demo():
    human = Human('Carson', 27)
    # human.age = 18  # you can't modify private members:_age  <-- this is defined by yourself.
    # human.k = 18  # 'Human' object has no attribute 'k'  <-- system error.
    age1 = human._age  # It's OK, although the IDE will show some warnings. (Access to a protected member _age of a class)

    age2 = human.age  # It's OK! see below:
    """
    if you do not define `__getattribute__` at the class of Human,
    the IDE will show you: Unresolved attribute reference 'age' for class 'Human'
    but it's ok on running since the MetaMemberControl will help you.
    """


if __name__ == '__main__':
    test_demo()

The metaclass is powerful, there are many things (such as monkey magic) you can do with it, but be careful this may only be known to you.

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 class and their instances The term metaclass simply means something used to create classes. In other words, it is the class of a class. The metaclass is used to create the class so like the object being an instance of a class, a class is an instance of a metaclass. In python classes are also considered objects.

The top answer is correct.

But readers may be coming here searching answers about similarly named inner classes. They are present in popular libraries, such as Django and WTForms.

As DavidW points out in the comments beneath this answer, these are library-specific features and are not to be confused with the advanced, unrelated Python language feature with a similar name.

Rather, these are namespaces within classes' dicts. They are constructed using inner classes for sake of readability.

In this example special field, abstract is visibly separate from fields of Author model.

from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()

    class Meta:
        abstract = True

Another example is from the documentation for WTForms:

from wtforms.form import Form
from wtforms.csrf.session import SessionCSRF
from wtforms.fields import StringField

class MyBaseForm(Form):
    class Meta:
        csrf = True
        csrf_class = SessionCSRF

    name = StringField("name")

This syntax does not get special treatment in the python programming language. Meta is not a keyword here, and does not trigger metaclass behavior. Rather, third-party library code in packages like Django and WTForms reads this property in the constructors of certain classes, and elsewhere.

The presence of these declarations modifies the behavior of the classes that have these declarations. For example, WTForms reads self.Meta.csrf to determine if the form needs a csrf field.

A class, in Python, is an object, and just like any other object, it is an instance of "something". This "something" is what is termed as a Metaclass. This metaclass is a special type of class that creates other class's objects. Hence, metaclass is responsible for making new classes. This allows the programmer to customize the way classes are generated.

To create a metaclass, overriding of new() and init() methods is usually done. new() can be overridden to change the way objects are created, while init() can be overridden to change the way of initializing the object. Metaclass can be created by a number of ways. One of the ways is to use type() function. type() function, when called with 3 parameters, creates a metaclass. The parameters are :-

  1. Class Name
  2. Tuple having base classes inherited by class
  3. A dictionary having all class methods and class variables

Another way of creating a metaclass comprises of 'metaclass' keyword. Define the metaclass as a simple class. In the parameters of inherited class, pass metaclass=metaclass_name

Metaclass can be specifically used in the following situations :-

  1. when a particular effect has to be applied to all the subclasses
  2. Automatic change of class (on creation) is required
  3. By API developers

I saw an interesting use case for metaclasses in a package called classutilities. It checks if all class variables are in upper case format (it is convenient to have unified logic for configuration classes), and checks if there are no instance level methods in class. Another interesting example for metaclases was deactivation of unittests based on complex conditions (checking values of multiple environmental variables).

In Python, a metaclass is a subclass of a subclass that determines how a subclass behaves. A class is an instance of another metaclass. In Python, a class specifies how the class's instance will behave.

Since metaclasses are in charge of class generation, you can write your own custom metaclasses to change how classes are created by performing additional actions or injecting code. Custom metaclasses aren't always important, but they can be.

look this:

Python 3.10.0rc2 (tags/v3.10.0rc2:839d789, Sep  7 2021, 18:51:45) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class Object:
...     pass
... 
>>> class Meta(type):
...     test = 'Worked!!!'
...     def __repr__(self):
...             return 'This is "Meta" metaclass'
... 
>>> class ObjectWithMetaClass(metaclass=Meta):
...     pass
... 
>>> Object or type(Object())
<class '__main__.Object'>
>>> ObjectWithMetaClass or type(ObjectWithMetaClass())
This is "Meta" metaclass
>>> Object.test
AttributeError: ...
>>> ObjectWithMetaClass.test
'Worked!!!'
>>> type(Object)
<class 'type'>
>>> type(ObjectWithMetaClass)
<class '__main__.Meta'>
>>> type(type(ObjectWithMetaClass))
<class 'type'>
>>> Object.__bases__
(<class 'object'>,)
>>> ObjectWithMetaClass.__bases__
(<class 'object'>,)
>>> type(ObjectWithMetaClass).__bases__
(<class 'type'>,)
>>> Object.__mro__
(<class '__main__.Object'>, <class 'object'>)
>>> ObjectWithMetaClass.__mro__
(This is "Meta" metaclass, <class 'object'>)
>>> 

In other words, when an object was not created (type of object), we looking MetaClass.

Meta is a Greek word which means 'after' or 'beyond'. Generally meta referring to self. Meta represents the additional information. Meta class is a helper class to explicitly tell about any additional information that has to be mentioned or any additional thing that has to be added about to the super or parent class. In python, when you define a class, it automatically takes it as a type=metaclass and this class functionality (behavior-methods, properties-self information) is applicable to other child class when created.

Here is a detailed explanation of what is a meta class and how it works, with coding examples.

Related