In Python, everything is an object —including classes themselves!
Just as an object is an instance of a class, a class is an instance of a Metaclass .
Understanding how classes are constructed in memory allows you to build powerful frameworks (like Django's ORM, SQLAlchemy, or Pydantic) that intercept class creation, validate attributes, and automatically register plugins.
When you write class User: ..., Python doesn't just execute the block; it passes the class name, bases, and dictionary of attributes to the built-in metaclass type :
1 # Creating a class dynamically using type(name, bases, dict):
2 def speak ( self ) :
3 return f"Hello, my name is { self . name } "
4
5 Student = type ( "Student" , ( ) , { "name" : "Aarav" , "speak" : speak } )
6
7 s = Student ( )
8 print ( type ( Student ) ) # <class 'type'>
9 print ( s . speak ( ) ) # Hello, my name is Aarav
A custom metaclass inherits from type. It intercepts the creation of a class before it enters the global namespace:
1 class EnforceSnakeCaseMeta ( type ) :
2 def __new__ ( cls , name , bases , dct ) :
3 # Inspect all defined methods:
4 for attr_name in dct :
5 if not attr_name . startswith ( "__" ) and callable ( dct [ attr_name ] ) :
6 if any ( c . isupper ( ) for c in attr_name ) :
7 raise TypeError ( f"Method ' { attr_name } ' in class ' { name } ' must be snake_case!" )
8 return super ( ) . __new__ ( cls , name , bases , dct )
9
10 # Using the metaclass:
11 class ValidService ( metaclass = EnforceSnakeCaseMeta ) :
12 def compute_fees ( self ) : # ✅ Valid snake_case
13 pass
14
15 # ❌ TypeError: Method 'ComputeFees' in class 'InvalidService' must be snake_case!
16 # class InvalidService(metaclass=EnforceSnakeCaseMeta):
17 # def ComputeFees(self):
18 # pass
Writing full metaclasses is complex and frequently leads to multiple-metaclass inheritance conflicts.
Python 3.6 introduced __init_subclass__ (PEP 487). It provides 95% of the power of metaclasses with zero metaclass boilerplate!
1 class PluginBase :
2 registry : dict [ str , type ] = { }
3
4 def __init_subclass__ ( cls , plugin_name : str , ** kwargs ) :
5 super ( ) . __init_subclass__ ( ** kwargs )
6 # Automatically register any child class that inherits from PluginBase:
7 cls . registry [ plugin_name ] = cls
8 print ( f"Registered plugin: ' { plugin_name } ' -> { cls . __name__ } " )
9
10 # Subclasses simply declare custom kwargs in their inheritance header:
11 class PDFExportPlugin ( PluginBase , plugin_name = "pdf" ) :
12 pass
13
14 class ExcelExportPlugin ( PluginBase , plugin_name = "excel" ) :
15 pass
16
17 print ( "Available Plugins in Registry:" , list ( PluginBase . registry . keys ( ) ) )
18 # ['pdf', 'excel']
Interactive Quiz • Knowledge Check
Practice Quiz In Python's object model, what is the default metaclass of all standard classes?
A object
B type
C class
D module
Which method in a custom metaclass is responsible for allocating and creating the new class object?
A __init__
B __new__
C __call__
D __prepare__
Which PEP introduced __init_subclass__ as a simpler alternative to custom metaclasses?
A PEP 8
B PEP 487
C PEP 557
D PEP 654
When does the __init_subclass__ method execute?
A When an instance of the child class is instantiated
B At class definition time when a child class inherits from the parent
C When garbage collection runs
D Only inside a thread
Why is __init_subclass__ preferred over full metaclasses for class registration?
A It runs 10x faster
B It avoids metaclass conflicts in multiple inheritance and requires much simpler syntax
C It allows running classes in C++
D It disables class inheritance
In the next lesson, we will integrate our advanced OOP skills to build Project: Employee Management System (1: Advanced OOP Concepts).
👉 Continue to Next Lesson: Project: Employee Management System →