Metaclasses are one of those Python features that sound complicated but are actually based on a simple idea:
Classes create objects.
Metaclasses create classes.
That’s it.
When you write:
class User:
pass
the class User is actually an object, and Python needs something to build that object.
By default, Python uses the metaclass called type:
print(type(User))
Output:
<class 'type'>
So type is the “class-maker.”
Why Would You Ever Use a Metaclass?
Most people never do — and that’s fine.
But frameworks like Django, SQLAlchemy, and Pydantic use metaclasses to:
add extra attributes to classes
validate or modify classes at creation time
automatically register subclasses
build features with less boilerplate
A metaclass lets you run logic when the class is created, not when it runs.
A Basic Metaclass Example
This metaclass prints the name of the class being created:
class LoggerMeta(type):
def __new__(cls, name, bases, attrs):
print("Creating:", name)
return super().__new__(cls, name, bases, attrs)
Using it:
class Example(metaclass=LoggerMeta):
pass
When the file loads, it prints:
Creating: Example
Because the metaclass runs before the class exists.
Adding Automatic Attributes
A more practical example:
class InfoMeta(type):
def __new__(cls, name, bases, attrs):
attrs["source"] = "auto"
return super().__new__(cls, name, bases, attrs)
Usage:
class Product(metaclass=InfoMeta):
pass
print(Product.source)
Output:
auto
The metaclass quietly added the attribute.
When to Use Metaclasses
Use them only when you need to control how classes are built — usually in libraries or frameworks.
Normal applications almost never need them.
Top comments (0)