Metaclasses in Python (The Most Advanced OOP Concept)
Metaclasses in Python (The Most Advanced OOP Concept)
Metaclasses are the class of a class.
In Python: - Objects are created from classes - Classes are created from metaclasses
Default metaclass: type
1. What is a Metaclass?
Everything in Python is an object:
- 10 → object
- "hello" → object
- class → object
But classes themselves are created by something:
👉 That something is a METACLASS
Flow of Creation
Object creation flow:
Instance → Class → Metaclass (type)
Graph
Instance (obj) ↓ Class (MyClass) ↓ Metaclass (type)
2. type() — The Built-in Metaclass
type() has 3 uses:
(1) Check type
x = 10
print(type(x))
Output: int
(2) Create class dynamically
MyClass = type(
"MyClass",
(),
{"x": 10}
)
obj = MyClass()
print(obj.x)
Output: 10
Graph
type() ↓ Creates class dynamically ↓ Class becomes object
Real World Example
Dynamic API models: - frameworks create classes at runtime - ORM models (Django)
3. Custom Metaclass
We can control class creation using metaclasses.
Example
class MyMeta(type):
def __new__(cls, name, bases, dct):
print("Creating class:", name)
return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=MyMeta):
x = 10
obj = MyClass()
Output: Creating class: MyClass
What is happening?
- Class definition starts
- Metaclass intercepts creation
- __new__ runs
- Class is modified/created
Graph
Class Definition ↓ Metaclass (__new__) ↓ Class Created ↓ Object Instantiated
4. Why Metaclasses Exist
They allow:
- Automatic validation
- Class modification
- Framework automation
- Enforcing rules
Real World Example (Framework Style)
class Meta(type):
def __new__(cls, name, bases, dct):
if "run" not in dct:
raise Exception("Class must define run()")
return super().__new__(cls, name, bases, dct)
class Service(metaclass=Meta):
def run(self):
print("Running service")
If you remove run():
Exception: Class must define run()
5. Django ORM Example (Conceptual)
Django models behave like:
class User(models.Model):
name = models.CharField()
Internally: - metaclass reads fields - builds SQL mapping - registers model
6. Custom Metaclass with Modification
class UpperMeta(type):
def __new__(cls, name, bases, dct):
new_dct = {}
for k, v in dct.items():
if not k.startswith("__"):
new_dct[k.upper()] = v
else:
new_dct[k] = v
return super().__new__(cls, name, bases, new_dct)
class Demo(metaclass=UpperMeta):
name = "Aman"
age = 20
print(hasattr(Demo, "name"))
print(hasattr(Demo, "NAME"))
Output: False True
7. Real World Use Cases
| System | Use of Metaclass |
|---|---|
| Django ORM | model creation |
| Pydantic | validation schema |
| ORMs | table mapping |
| Frameworks | auto registration |
8. type vs Custom Metaclass
| Feature | type | Custom Metaclass |
|---|---|---|
| Built-in | Yes | No |
| Control | Low | High |
| Framework use | Internal | Advanced |
9. Common Mistakes
Mistake 1: Confusing object vs class
Wrong thinking: metaclass creates objects
Correct: metaclass creates classes
Mistake 2: Overusing metaclasses
Metaclasses are powerful but rare in application code.
Use only when needed.
Mistake 3: Forgetting type inheritance
class Meta(type):
pass
10. Graph: Full Python Object Model
value ↓ object instance ↓ class ↓ metaclass (type) ↓ Python runtime
11. Real World Analogy
| Concept | Real World |
|---|---|
| Object | Employee |
| Class | Job Role |
| Metaclass | HR system defining roles |
12. Homework 1
Create a metaclass that: - prints class name - blocks classes without method "execute"
Solution:
class CheckMeta(type):
def __new__(cls, name, bases, dct):
if "execute" not in dct:
raise Exception("Missing execute method")
print("Creating:", name)
return super().__new__(cls, name, bases, dct)
class Job(metaclass=CheckMeta):
def execute(self):
print("Running job")
13. Homework 2
Create metaclass that converts all attributes to uppercase.
Solution:
class UpperMeta(type):
def __new__(cls, name, bases, dct):
new_dct = {}
for k, v in dct.items():
if not k.startswith("__"):
new_dct[k.upper()] = v
else:
new_dct[k] = v
return super().__new__(cls, name, bases, new_dct)
class Test(metaclass=UpperMeta):
value = 100
print(hasattr(Test, "VALUE"))
14. Why Metaclasses Matter
They power: - Django ORM - Flask extensions - FastAPI internals - Pydantic validation - Dependency injection systems
15. Final Mental Model
Class creation process:
- Python reads class
- Metaclass intercepts
- Class is modified/generated
- Object is created from class
Next Advanced Topics
- __new__ vs __init__ deep dive
- Descriptor + Metaclass combination
- Django ORM internals
- Dependency Injection systems
- Python interpreter internals
- AST (Abstract Syntax Tree) ```