Python Inner Classes
In this page:
class OuterClass:
class InnerClass:
# inner members
inner_object = OuterClass.InnerClass()
What Is an Inner Class
An inner class is simply a class defined inside the body of another class, which nests its name inside the outer class's namespace — you access it as Outer.Inner rather than as a free-standing top-level name.
It's a way to signal that the inner class only makes sense in the context of its outer class.
Example: What Is an Inner Class
class Outer:
class Inner: # class nested inside another class
pass
print(Outer.Inner) # accessed as Outer.Inner, not a top-level name
Why Use an Inner Class
Inner classes are useful when a helper class is tightly coupled to one specific outer class and has no meaning on its own — nesting it communicates that relationship directly in the code structure and avoids cluttering the module's top-level namespace with a name only one other class ever uses.
Example: Why Use an Inner Class
class Car:
class Engine: # tightly coupled helper, only meaningful within Car
def start(self):
print("Engine started")
Car.Engine().start()
Instantiating an Inner Class
You create an instance of an inner class the same way as any class, just through its qualified path — Outer.Inner() — and the inner class instance has no automatic special link back to any particular outer instance unless you pass one in explicitly.
Example: Instantiating an Inner Class
class Outer:
class Inner:
def __init__(self):
self.value = 42
obj = Outer.Inner() # instantiated through its qualified path
print(obj.value)
Inner Classes vs Separate Top-Level Classes
Nothing about nesting is required by the language — you could always write a separate top-level class instead, and most Python style guides actually prefer that for anything beyond a small tightly-scoped helper, since nesting makes the inner class harder to reuse, test, or reference from other modules.
Example: Inner Classes vs Separate Top-Level Classes
class Engine:
def start(self):
print("Engine started")
class Car:
def __init__(self):
self.engine = Engine() # composition using a separate top-level class instead of nesting
Car().engine.start()
Accessing Outer Class State
An inner class doesn't automatically have access to its outer class's instance attributes the way a nested function closure would — if the inner class needs data from the outer instance, that data has to be passed in explicitly, usually through the inner class's constructor.
Example: Accessing Outer Class State
class Car:
class Engine:
def __init__(self, owner_name):
self.owner_name = owner_name # data passed in explicitly, not inherited from Car
def __init__(self, owner_name):
self.engine = Car.Engine(owner_name) # owner_name is forwarded to the inner class
car = Car("Alex")
print(car.engine.owner_name)
- Trying to create the inner class as
Inner()directly, when it must be reached through the outer class, as inOuter.Inner(). - Expecting the inner class to access the outer instance automatically, when it does not; you must pass the outer object in.
- Nesting a class that is used everywhere, when a normal top-level class would be simpler to import and test.
- Classes and objects, constructors, and inheritance form the core of Python OOP.
- Multiple inheritance, polymorphism, encapsulation, and abstraction organize code.
- Magic methods, property decorators, and inner classes add more features.
Chapter Quiz — Complete all 11 topics to unlock
0/11 topics done
Complete these topics first: