How do tools like dataclasses and pydantic create the __init__() functions for the classes they create?
I know I can use these tools but I want to learn how to use the python metaprogramming to parse my class and create a dynamic init function based on attributes and their types.
an example:
class MyClass:
x: int
y: str | None
z: float = 0.1
# I don't want to manually make this
def __init__(self, x: int, y: str | None, z: float = 0.1):
self.x = x
self.y = y
self.z = z
Is it possible to do something similar using metaclasses and type annotations?
There are two main approaches:
The idea for
dataclassis that you need to somehow get all the annotations and build that method manually from a string(I'll show you). In this scenario you have the class object created.Available tools are:
typingmodule hasget_type_hintsfunction.__dict__.exec()to dynamically create objects. (dataclass literally does this)output:
Of course this is a naive approach and has some problems but it gives you the overview of the idea.
dataclassandpydantic(which I'll show after) do a lot of other stuff as well.Another approach which is used by Pydantic is using a metaclass. The difference is that with decorators, the class is created first and then you extract the information you want but in metaclasses the information is available in the
namespaceparameter of the__new__"before creating that class": (I won't go to implement it because the concept is the same as before)output:
Now you can now check the actual source codes and follow their implementation.
Also note that there are many helpful functions in
inspectmodule that let's you inspect many information from objects in runtime.