How Python Classes Are Created
Understand type, the default metaclass, and class creation hooks.
How Python Classes Are Created is a free Python Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Python Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
type() is a Metaclass
Every class in Python is an instance of type. type is itself a class — it is the metaclass of all metaclasses.
# These are equivalent:
class Dog:
sound = "woof"
Dog2 = type("Dog2", (), {"sound": "woof"})
print(type(Dog)) # <class 'type'>
print(type(Dog2)) # <class 'type'>type() Three-Argument Form
type(name, bases, namespace) creates a new class dynamically. This is exactly what class statements do under the hood.
Animal = type("Animal", (), {"speak": lambda self: "..."})
Dog = type("Dog", (Animal,), {"speak": lambda self: "woof"})
d = Dog()
print(d.speak()) # woofClass Creation Steps
When Python sees a class statement it: 1) resolves the metaclass, 2) prepares the namespace, 3) executes the class body, 4) calls metaclass(name, bases, namespace).
# class Foo(Base, metaclass=Meta):
# x = 1
#
# Equivalent to:
# namespace = Meta.__prepare__("Foo", (Base,))
# exec(class_body, namespace)
# Foo = Meta("Foo", (Base,), namespace)__prepare__
__prepare__(name, bases, **kw) is a class method on the metaclass that returns the namespace dict used during class body execution. Override it to use an OrderedDict or custom mapping.
class OrderedMeta(type):
@classmethod
def __prepare__(mcs, name, bases, **kw):
print(f"Preparing namespace for {name}")
return {}
class MyClass(metaclass=OrderedMeta):
x = 1
y = 2__new__ vs __init__ in type
type.__new__ creates the class object; type.__init__ initializes it. For metaclasses, override __new__ to customise class creation.
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kw):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kw)
return cls._instances[cls]
class DB(metaclass=Singleton):
pass
print(DB() is DB()) # TrueClass Decorators vs Metaclasses
Class decorators apply post-creation; metaclasses control creation itself. For simple augmentation, prefer decorators. Use metaclasses when you need to affect the creation process.
def add_repr(cls):
cls.__repr__ = lambda self: f"{cls.__name__}()"
return cls
@add_repr
class Widget:
pass
print(Widget()) # Widget()__init_subclass__
__init_subclass__ is called on the base class whenever a subclass is defined. A lightweight alternative to metaclasses for customising subclass behaviour.
class Plugin:
_registry = []
def __init_subclass__(cls, **kw):
super().__init_subclass__(**kw)
Plugin._registry.append(cls)
class AudioPlugin(Plugin): pass
class VideoPlugin(Plugin): pass
print(Plugin._registry) # [AudioPlugin, VideoPlugin]ABCMeta
ABCMeta is a built-in metaclass that powers abstract base classes via @abstractmethod.
from abc import ABCMeta, abstractmethod
class Shape(metaclass=ABCMeta):
@abstractmethod
def area(self): ...
class Circle(Shape):
def __init__(self, r): self.r = r
def area(self): return 3.14159 * self.r ** 2
# Shape() # TypeError: Can't instantiate abstract classInspecting a Class's Metaclass
Use type(cls) to find a class's metaclass and cls.__mro__ to see the method resolution order.
class Meta(type): pass
class Foo(metaclass=Meta): pass
print(type(Foo)) # <class '__main__.Meta'>
print(Foo.__mro__) # (Foo, object)Metaclass Inheritance
A class's metaclass is inherited by its subclasses. If two bases have different metaclasses, the most derived must be used (or a conflict arises).
class MyMeta(type): pass
class Base(metaclass=MyMeta): pass
class Child(Base): pass # Child's metaclass is also MyMeta
print(type(Child)) # <class '__main__.MyMeta'>When to Use Metaclasses
Use metaclasses for: auto-registering subclasses, enforcing class invariants, ORM field detection (like Django's Model), and API framework routing. For most cases, use __init_subclass__ or class decorators instead.
# Real-world: Django ORM uses ModelBase metaclass
# to collect field definitions into _meta
# You rarely need a custom metaclass;
# __init_subclass__ covers most plugin/registration patternsQuick Check
What does type("Dog", (Animal,), {"speak": lambda self: "woof"}) do?
Recap
Every class is an instance of type. The class creation pipeline: resolve metaclass → prepare namespace → execute body → call metaclass. Prefer __init_subclass__ for simple subclass hooks; use a full metaclass only when you need to control class creation itself.
Frequently asked questions
Is the “How Python Classes Are Created” lesson free?
Yes — the full text of “How Python Classes Are Created” is free to read here on the web, and the Python Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Python Academy course, upgrade to CoddyKit PRO.
What will I learn in “How Python Classes Are Created”?
Understand type, the default metaclass, and class creation hooks. You practise Python Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Python Academy?
No prior experience is required. Python Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “How Python Classes Are Created” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Python Academy lesson?
Yes. Every Python Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- How Python Classes Are Created
- Writing Custom Metaclasses
- Descriptors: __get__, __set__, __delete__
- __slots__ and Memory Optimization