Metaclasses & Object Construction
Topic 1 of 7, with 3 concept checks. __new__ vs __init__, and how classes are actually built
Follow class creation from namespace to instance
Class construction
Trace how Python prepares a class namespace, invokes a metaclass, creates the class object, and later constructs instances before deciding whether customization is justified.
Core lesson 01
__new__(cls, ...) is a static method that creates and returns a new instance, called before the instance exists. __init__(self, ...) then initializes that already-created instance and returns nothing.
Object creation is actually two steps in Python. __new__ is responsible for allocating and returning a new instance of the class (implicitly a staticmethod, taking cls first). Python then calls __init__ on that returned instance to set up its initial state. Overriding __init__ is common; overriding __new__ is rare, mainly used for immutable-type subclassing or enforcing patterns like singletons where you need to control which object gets returned before initialization even happens.
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
print("creating the one instance")
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
print("init runs every time __init__ is called")
a = Singleton()
b = Singleton()
print(a is b) # True -- same object
# note: __init__ still runs twice, once per Singleton() callWhat to remember
What's the difference between __new__ and __init__?
Common footguns
- Assuming overriding __new__ alone prevents __init__ from re-running on repeat calls — it doesn't; __init__ always runs after __new__ returns, even if __new__ returned an existing object.
Core lesson 02
A metaclass is the class of a class — it controls how classes themselves are created. type is the default metaclass; class Foo: ... is really syntactic sugar for calling type('Foo', bases, namespace).
Just as instantiating a class produces an object, 'instantiating' a metaclass produces a class. By default, every class's metaclass is type — when Python executes a class statement, it's effectively calling type(name, bases, namespace) to build the class object. A custom metaclass (a subclass of type) can hook into that process — validating class definitions, auto-registering subclasses, injecting methods — by overriding __new__ or __init__ on the metaclass itself.
class Meta(type):
def __new__(mcls, name, bases, namespace):
print(f"creating class {name}")
return super().__new__(mcls, name, bases, namespace)
class MyClass(metaclass=Meta):
pass
# prints: creating class MyClass -- this runs at class-DEFINITION time, not instantiationWhat to remember
What is a metaclass, and what does 'type is the metaclass of all classes' mean?
Common footguns
- Reaching for a metaclass to solve a problem a simpler tool (a decorator, __init_subclass__, or a plain base class) would solve more clearly — metaclasses hurt readability if overused.
Core lesson 03
__init_subclass__(cls) is a classmethod on a base class that Python calls automatically whenever a subclass is defined — covers the most common metaclass use case without the complexity of a full metaclass.
Before Python 3.6, reacting to 'a new subclass was just defined' required a metaclass. __init_subclass__ provides the same hook as a plain classmethod on the class you want to watch — much easier to read and reason about, and composes better with normal inheritance.
class Plugin:
registry = []
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
Plugin.registry.append(cls)
class PluginA(Plugin): pass
class PluginB(Plugin): pass
print(Plugin.registry) # [<class PluginA>, <class PluginB>] -- auto-registeredWhat to remember
What's a simpler alternative to a metaclass for reacting to subclass creation?
Common footguns
- Forgetting super().__init_subclass__(**kwargs) — breaks cooperative behavior if a chain of subclasses also uses this hook.
Python lab
Browser Python lab
Runtime · idle
Python loads on your first run. Your code stays in this browser.
Best practices
- Reach for __init_subclass__ before a full metaclass for subclass registration/validation — simpler and clearer.
- Override __new__ only for immutable-type subclassing or true singleton-style construction control.
- Keep metaclasses (if used at all) narrowly scoped and well documented — they affect anyone who ever subclasses the class.
- Prefer composition, decorators, or class decorators over metaclasses for most 'inject behavior into classes' needs.
Apply the concept in Interview practice
Design Search Autocomplete SystemhardLeetCode #642 · O(p) per keystroke (p = matches)
Build a trie of past sentences with frequency counts; on each keystroke walk to the current trie node and return the top 3 matches by frequency then lexicographic order.
Open problemLogger Rate LimitereasyLeetCode #359 · O(1) per message
Keep a dict of message -> last-printed timestamp; allow a message through only if it hasn't been seen in the last 10 seconds — a class-level registry pattern similar to what metaclasses often manage.
Open problemConcept checks
What's the difference between __new__ and __init__?
Hint
One creates the object, the other configures it after creation.
__new__ returns the instance; __init__ receives it and sets it up.
Answer
__new__(cls, ...) is a static method that creates and returns a new instance, called before the instance exists. __init__(self, ...) then initializes that already-created instance and returns nothing.
Object creation is actually two steps in Python. __new__ is responsible for allocating and returning a new instance of the class (implicitly a staticmethod, taking cls first). Python then calls __init__ on that returned instance to set up its initial state. Overriding __init__ is common; overriding __new__ is rare, mainly used for immutable-type subclassing or enforcing patterns like singletons where you need to control which object gets returned before initialization even happens.
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
print("creating the one instance")
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
print("init runs every time __init__ is called")
a = Singleton()
b = Singleton()
print(a is b) # True -- same object
# note: __init__ still runs twice, once per Singleton() callWatch out
- Assuming overriding __new__ alone prevents __init__ from re-running on repeat calls — it doesn't; __init__ always runs after __new__ returns, even if __new__ returned an existing object.
What is a metaclass, and what does 'type is the metaclass of all classes' mean?
Hint
A metaclass is to a class what a class is to an instance.
type() is both a function you know and the default metaclass.
Answer
A metaclass is the class of a class — it controls how classes themselves are created. type is the default metaclass; class Foo: ... is really syntactic sugar for calling type('Foo', bases, namespace).
Just as instantiating a class produces an object, 'instantiating' a metaclass produces a class. By default, every class's metaclass is type — when Python executes a class statement, it's effectively calling type(name, bases, namespace) to build the class object. A custom metaclass (a subclass of type) can hook into that process — validating class definitions, auto-registering subclasses, injecting methods — by overriding __new__ or __init__ on the metaclass itself.
class Meta(type):
def __new__(mcls, name, bases, namespace):
print(f"creating class {name}")
return super().__new__(mcls, name, bases, namespace)
class MyClass(metaclass=Meta):
pass
# prints: creating class MyClass -- this runs at class-DEFINITION time, not instantiationWatch out
- Reaching for a metaclass to solve a problem a simpler tool (a decorator, __init_subclass__, or a plain base class) would solve more clearly — metaclasses hurt readability if overused.
What's a simpler alternative to a metaclass for reacting to subclass creation?
Hint
Python added a hook specifically for this common case.
It's a classmethod defined on the base class, not a separate metaclass.
Answer
__init_subclass__(cls) is a classmethod on a base class that Python calls automatically whenever a subclass is defined — covers the most common metaclass use case without the complexity of a full metaclass.
Before Python 3.6, reacting to 'a new subclass was just defined' required a metaclass. __init_subclass__ provides the same hook as a plain classmethod on the class you want to watch — much easier to read and reason about, and composes better with normal inheritance.
class Plugin:
registry = []
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
Plugin.registry.append(cls)
class PluginA(Plugin): pass
class PluginB(Plugin): pass
print(Plugin.registry) # [<class PluginA>, <class PluginB>] -- auto-registeredWatch out
- Forgetting super().__init_subclass__(**kwargs) — breaks cooperative behavior if a chain of subclasses also uses this hook.