Metaclasses

class MyMeta(type):
    """
    We define a meta class: a meta class is a class describing what a class is.
    """

    def __new__(mcs, name, bases, dct):
        """
        called when the class is created
        :param mcs: the meta-class
        :param name: the name of the class that is created
        :param bases:
        :param dct: 

        """
        print(f'mcs: {mcs}\n name: {name}\n bases: {bases} \n dct: {dct}')
        return type.__new__(mcs, name, bases, dct)
    
    def __init__(self, *args, **kwargs):
        print(f'self: {self}\n args: {args}\n kwargs: {kwargs}')
        return type.__init__(self, *args, **kwargs)



class MyClass(metaclass=MyMeta):
    pass


# Instantiate the class
#my_instance = MyClass()

mcs: <class '__main__.MyMeta'>
 name: MyClass
 bases: () 
 dct: {'__module__': '__main__', '__qualname__': 'MyClass'}
self: <class '__main__.MyClass'>
 args: ('MyClass', (), {'__module__': '__main__', '__qualname__': 'MyClass'})
 kwargs: {}

Example of documentation checker

class MetaClassWithDoc(type):
    """
    This meta-class is like type but it checks at the creation (in __new__ of the class)
    that all methods have a docstring (__doc__ field is defined)
    """

    def __new__(cls, name, bases, dct):
        for attr, value in dct.items():
            if callable(value) and not value.__doc__:
                raise TypeError(f'Method {attr} must have a docstring')
        return super().__new__(cls, name, bases, dct)



class DocumentedClass(metaclass=MetaClassWithDoc):
    """
    All methods of this class should be documented. Otherwise, BOOM.
    """

    def method_with_docstring(self):
        """This method is documented."""
        pass

 #   def method_without_docstring(self):
  #      pass  # This will raise a TypeError

Example of timed classes

import types
from time import time


class TimerMetaClass(type):
    """
    meta-class for classes with methods that are timed
    """

    def __new__(mcs, name, bases, dct):
        def getTimedVerionOfMethod(name, method):
            def timedVersionFunctionOfMethod(self, *args, **kwargs):
                t = time()
                result = method(self, *args, **kwargs)
                print("Appel de %s :\t%s" % (name, time() - t))
                return result

            timedVersionFunctionOfMethod.__name__ = method.__name__
            timedVersionFunctionOfMethod.__doc__ = method.__doc__
            timedVersionFunctionOfMethod.__dict__ = method.__dict__
            return timedVersionFunctionOfMethod

        d = {}

        for name, slot in dct.items():
            if type(slot) is types.FunctionType:
                d[name] = getTimedVerionOfMethod(name, slot)
            else:
                d[name] = slot

        return type.__new__(mcs, name, bases, d)


class A(metaclass=TimerMetaClass):
    def m(self): pass


a = A()
a.m()