formations/python-avancé/examples/metaclass.py

71 lines
2.0 KiB
Python

class Meta(type):
@classmethod
def __prepare__(metacls, name, bases, **kwds):
"""Prepare the namespace in which the class will be executed."""
print(
"Meta.__prepare__(",
f"{metacls=},",
f"{name=},",
f"{bases=},",
f"{kwds=}) -> {{}}",
sep="\n ",
)
return {}
# __new__() is a static method (special-cased so you need not declare it as such)
def __new__(cls, name, bases, namespace, **kwds):
"""The class body is executed in a new namespace and the class name is
bound locally to the result of type(name, bases, namespace).
"""
print(
"\nMeta.__new__(",
f"{cls=},",
f"{name=},",
f"{bases=},",
f"{namespace=}",
f"{kwds=})",
sep="\n ",
end=" ",
)
returns = type.__new__(cls, name, bases, namespace)
print(f"-> {returns}\n")
return returns
def __init__(self, name, bases, namespace, **kwds):
"""This is the actual creation of the class !
As a class is an instance of its type."""
print(
"Meta.__init__(",
f"{self=},",
f"{name=},",
f"{bases=},",
f"{namespace=},",
f"{kwds=})",
sep="\n ",
end="\n\n"
)
class Classe(metaclass=Meta):
print("\nAfter Meta.__prepare__ is called, the interpreter executes the class body "
"like:")
print(" exec(body, globals(), ns)")
print("with `ns` the dict returned from __prepare__")
def __new__(cls, *args, **kwargs):
print(f"Classe.__new__({cls=}, {args=}, {kwargs=})")
returns = object.__new__(cls)
print(f" returns {returns}")
return returns
def __init__(self, *args, **kwargs):
print(f"Classe.__init__({self=}, {args=}, {kwargs=})")
print("Will now instantiate a Classe()")
Classe()