Quick answer: Python allows a class definition inside another class, but the nested class does not receive an implicit outer instance. Use this pattern for a tightly owned helper type or namespace; use a module-level class or composition when the helper has broad responsibilities or dependencies.

Nested classes in Python are classes defined inside another class. They are also called inner classes. A nested class can be useful when a small helper type belongs closely to one outer class and does not need to live in the module's top-level namespace.
Python does not require nested classes for normal object-oriented programming. Most classes should stay at module level because they are easier to import, test, and reuse. Use nesting only when the relationship is clear, such as a parser with small token types, a report with internal section objects, or a widget with private configuration helpers. The official Python tutorial on classes is the best starting point for the broader class model.
Basic Nested Class Syntax
A nested class is written inside the body of another class. You can access it through the outer class name, just like any other class attribute.
class Report:
class Header:
def __init__(self, title):
self.title = title
def render(self):
return f"# {self.title}"
header = Report.Header("Sales Summary")
print(header.render())
Here, Header is stored on Report. It is not automatically tied to a specific Report instance. This is one of the most important details to understand before using inner classes. The nested class is mainly a namespacing choice.
Create Inner Class Objects From the Outer Class
The outer class can create instances of its inner class inside methods. This pattern keeps construction logic near the outer type while still allowing the helper object to have its own methods.
class Report:
class Section:
def __init__(self, heading, text):
self.heading = heading
self.text = text
def render(self):
return f"## {self.heading}" + chr(10) + self.text
def make_section(self, heading, text):
return self.Section(heading, text)
report = Report()
section = report.make_section("Results", "Revenue increased.")
print(section.render())
This is clearer than scattering tiny helper classes across a module when they only make sense inside one outer type. For object inspection while debugging, the related guide to Python vars() can help show where attributes are stored.

Multiple Inner Classes
An outer class may contain more than one inner class. This can work well when each helper class represents a distinct part of the outer object's domain.
class Form:
class TextField:
def __init__(self, name):
self.name = name
class Checkbox:
def __init__(self, name, checked=False):
self.name = name
self.checked = checked
email = Form.TextField("email")
subscribe = Form.Checkbox("subscribe", checked=True)
print(email.name, subscribe.checked)
Multiple inner classes should still be small and focused. If an inner class grows large or becomes useful outside the outer class, move it to the module level. A useful rule is this: if another module wants to import the inner class directly, it probably deserves a top-level name.
Multilevel Nested Classes
Python allows more than one level of nesting, but deep nesting is rarely worth the readability cost. Use it only when the hierarchy genuinely improves clarity.
class Application:
class Settings:
class Database:
def __init__(self, host):
self.host = host
def url(self):
return f"postgres://{self.host}"
database = Application.Settings.Database("localhost")
print(database.url())
The syntax is valid, but it is also verbose. If code outside the class must frequently type Application.Settings.Database, a module-level DatabaseSettings class may be easier to read. Deep nesting also makes documentation and examples harder to scan.
Access Outer Instance Data Explicitly
An inner class does not automatically receive the outer instance's self. If the inner object needs outer data, pass that data explicitly. This keeps dependencies visible.
class Menu:
class Item:
def __init__(self, menu_name, label):
self.menu_name = menu_name
self.label = label
def full_label(self):
return f"{self.menu_name}: {self.label}"
def __init__(self, name):
self.name = name
def item(self, label):
return self.Item(self.name, label)
menu = Menu("File")
print(menu.item("Open").full_label())
This explicit style avoids a common misunderstanding: nesting changes the namespace, but it does not create automatic access to outer instance attributes. For related class vocabulary, see Python cls vs self.

When to Avoid Nested Classes
A nested class is not a privacy feature. Python class definitions are attributes, and code can still access Outer.Inner. Avoid nesting when the inner class is reused in several modules, needs independent tests, or makes import paths awkward. In those cases, a normal top-level class is clearer.
class Validator:
def __call__(self, value):
return isinstance(value, str) and bool(value.strip())
validator = Validator()
print(validator("Python"))
This top-level Validator is easier to reuse than a deeply nested helper. If your helper behaves like a function object, the guide to Python callable objects is a useful follow-up.
Testing and Organization Tips
Test inner classes the same way you test normal classes: instantiate them, call their methods, and assert the result. If testing requires too much setup from the outer class, that is a signal the inner class may be doing too much. Keep nested classes small enough that their relationship to the outer class is obvious.
Also consider how readers will find the type. A top-level class appears clearly in module documentation and search results. A nested class can be harder to discover, so it should earn its place by making the outer class easier to understand.

Nested Classes and Special Methods
Nested classes follow the same class-definition rules as any other class. Special methods such as __new__, __init__, and __repr__ work normally inside inner classes. Python's reference page on class definitions and the data model entry for object.__new__ explain the underlying mechanics. PythonPool also has a related article on Python __new__.
Conclusion
Use nested classes in Python when a helper type is tightly connected to one outer class and would add noise at module level. Keep inner classes small, pass outer instance data explicitly, and move the class outward if it becomes reusable. Clear organization is the real benefit; nesting alone does not make code private or automatically linked to an outer instance.
Define And Access A Nested Class
The inner class becomes an attribute on the outer class. It can be instantiated through that attribute, but its methods receive only the inner instance unless an outer object is passed explicitly.
class Report:
class Row:
def __init__(self, name, value):
self.name = name
self.value = value
row = Report.Row("accuracy", 0.91)
print(row.name, row.value)
Pass Outer State Explicitly
A nested class does not automatically see self from the outer class. Store the outer object or pass the required value explicitly, and make that dependency visible in the constructor so testing does not depend on hidden lookup.
class Parser:
def __init__(self, prefix):
self.prefix = prefix
class Token:
def __init__(self, parser, text):
self.parser = parser
self.text = text
parser = Parser("item:")
token = parser.Token(parser, "name")
print(token.parser.prefix, token.text)

Use A Class Attribute Carefully
A nested class can act as a namespaced constant or helper, but it is still a normal class object. It does not close over local variables like a nested function, and inheritance or serialization should be designed explicitly.
class Response:
class Status:
OK = 200
NOT_FOUND = 404
print(Response.Status.OK)
print(Response.Status.NOT_FOUND)
Compare Composition And Module Scope
Move a helper to module scope when it is reused by several outer types, needs independent documentation, or has its own lifecycle. Use composition when an object needs collaborators, and keep a nested class small when ownership is the important relationship.
from dataclasses import dataclass
@dataclass
class Coordinate:
x: float
y: float
class Shape:
def __init__(self, origin):
self.origin = origin
shape = Shape(Coordinate(0, 0))
print(shape.origin)
Nested classes are a namespace and ownership choice, not an automatic Java-style inner-object mechanism. Keep the public relationship simple and test the helper independently when it grows beyond a small type.
For related object-oriented design, compare TypedDict structures, super(), and cls versus self before choosing a nested type or a reusable module-level class.
Frequently Asked Questions
Can Python classes be defined inside other classes?
Yes. The inner class becomes an attribute of the outer class and can be accessed through that namespace.
Does a nested class automatically access the outer instance?
No. It does not receive an implicit outer self; pass the outer object explicitly or use composition when that dependency is central.
When should I use a nested class?
Use one for a tightly scoped helper type or namespace that should be discovered through the outer class, not merely to hide a large unrelated abstraction.
What is an alternative to nested classes?
A module-level class, composition, a dataclass, or a private helper often makes dependencies and testing clearer.
Can we have a nested static class in the class method?
Yes. Since the methods of a nested class cannot directly access the instance attributes of the outer class. The nested inner class is kind of a static class.
Regards,
Pratik
requires output to be
Thank you for pointing it out. I’ve updated it accordingly.