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()
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
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()