Python Programming Deep Dive · Practical Python

Object-Oriented Programming in Python

Classes, inheritance, and dunder methods

Object-Oriented Programming in Python

Classes bundle data and behavior together. __init__ initializes new instances, and self refers to the instance inside methods.

class Rectangle:
    def __init__(self, width: float, height: float):
        self.width = width
        self.height = height

    def area(self) -> float:
        return self.width * self.height

Inheritance and Dunder Methods

Subclasses inherit and can override behavior. Special "dunder" methods like __str__, __eq__, and __len__ let custom objects integrate with built-in functions such as print(), ==, and len().

class Square(Rectangle):
    def __init__(self, side: float):
        super().__init__(side, side)

Practice questions

What is `self` in a Python method, and why must it be listed explicitly as the first parameter?

Answer

Summary

self refers to the specific instance the method was called on; Python requires it explicitly (rather than implying it, like some other languages) so the mechanism of attribute access stays explicit and consistent.

Longer Answer

self refers to the specific instance the method was called on; Python requires it explicitly (rather than implying it, like some other languages) so the mechanism of attribute access stays explicit and consistent. Unlike languages where 'this'/'self' is implicit, Python makes it a real, visible parameter — which is why you'll get an error if you forget it in a method signature. In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview.

Key Points

  • self refers to the specific instance the method was called on; Python requires it explicitly (rather than implying it, like some other languages) so the mechanism of attribute access stays explicit and consistent
  • Unlike languages where 'this'/'self' is implicit, Python makes it a real, visible parameter — which is why you'll get an error if you forget it in a method signature
  • In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview
  • Use the answer to connect the concept back to a realistic production or interview scenario for 'What is self in a Python method, and why must it be listed explicitly as the first parameter?'

Comparison / Tradeoffs

Aspect Notes
Core idea self refers to the specific instance the method was called on; Python requires it explicitly (rather than implying it, like some other languages) so the mechanism of attribute access stays explicit and consistent.
Practical tradeoff Unlike languages where 'this'/'self' is implicit, Python makes it a real, visible parameter — which is why you'll get an error if you forget it in a method signature.

Why

Summary

Unlike languages where 'this'/'self' is implicit, Python makes it a real, visible parameter — which is why you'll get an error if you forget it in a method signature.

Longer Answer

Unlike languages where 'this'/'self' is implicit, Python makes it a real, visible parameter — which is why you'll get an error if you forget it in a method signature. In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview.

Key Points

  • Unlike languages where 'this'/'self' is implicit, Python makes it a real, visible parameter — which is why you'll get an error if you forget it in a method signature
  • In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview
  • In an interview, relate 'What is self in a Python method, and why must it be listed explicitly as the first parameter?' to implementation decisions, tradeoffs, and operational impact
  • Use the answer to connect the concept back to a realistic production or interview scenario for 'What is self in a Python method, and why must it be listed explicitly as the first parameter?'

Comparison / Tradeoffs

Aspect Notes
Core idea Unlike languages where 'this'/'self' is implicit, Python makes it a real, visible parameter — which is why you'll get an error if you forget it in a method signature.
Practical tradeoff In an interview, relate 'What is self in a Python method, and why must it be listed explicitly as the first parameter?' to implementation decisions, tradeoffs, and operational impact.
What do dunder methods like `__str__`, `__eq__`, and `__len__` actually enable?

Answer

Summary

They let a custom class hook into Python's built-in operators and functions — defining __eq__ makes == work meaningfully for your objects, __len__ makes len(obj) work, and so on.

Longer Answer

They let a custom class hook into Python's built-in operators and functions — defining __eq__ makes == work meaningfully for your objects, __len__ makes len(obj) work, and so on. This is Python's operator-overloading mechanism — implement the right dunder method and built-in syntax 'just works' for your type. In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview.

Key Points

  • They let a custom class hook into Python's built-in operators and functions — defining __eq__ makes == work meaningfully for your objects, __len__ makes len(obj) work, and so on
  • This is Python's operator-overloading mechanism — implement the right dunder method and built-in syntax 'just works' for your type
  • In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview
  • Use the answer to connect the concept back to a realistic production or interview scenario for 'What do dunder methods like __str__, __eq__, and __len__ actually enable?'

Comparison / Tradeoffs

Aspect Notes
Core idea They let a custom class hook into Python's built-in operators and functions — defining __eq__ makes == work meaningfully for your objects, __len__ makes len(obj) work, and so on.
Practical tradeoff This is Python's operator-overloading mechanism — implement the right dunder method and built-in syntax 'just works' for your type.

Why

Summary

This is Python's operator-overloading mechanism — implement the right dunder method and built-in syntax 'just works' for your type.

Longer Answer

This is Python's operator-overloading mechanism — implement the right dunder method and built-in syntax 'just works' for your type. In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview.

Key Points

  • This is Python's operator-overloading mechanism — implement the right dunder method and built-in syntax 'just works' for your type
  • In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview
  • In an interview, relate 'What do dunder methods like __str__, __eq__, and __len__ actually enable?' to implementation decisions, tradeoffs, and operational impact
  • Use the answer to connect the concept back to a realistic production or interview scenario for 'What do dunder methods like __str__, __eq__, and __len__ actually enable?'

Comparison / Tradeoffs

Aspect Notes
Core idea This is Python's operator-overloading mechanism — implement the right dunder method and built-in syntax 'just works' for your type.
Practical tradeoff In an interview, relate 'What do dunder methods like __str__, __eq__, and __len__ actually enable?' to implementation decisions, tradeoffs, and operational impact.
How does `super().__init__(...)` help when a subclass overrides `__init__`?

Answer

Summary

It calls the parent class's constructor explicitly, so the subclass can add its own setup on top of the parent's initialization instead of having to duplicate the parent's logic.

Longer Answer

It calls the parent class's constructor explicitly, so the subclass can add its own setup on top of the parent's initialization instead of having to duplicate the parent's logic. This is the standard way to build on inherited behavior rather than re-implementing it from scratch in every subclass. In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview.

Key Points

  • It calls the parent class's constructor explicitly, so the subclass can add its own setup on top of the parent's initialization instead of having to duplicate the parent's logic
  • This is the standard way to build on inherited behavior rather than re-implementing it from scratch in every subclass
  • In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview
  • Use the answer to connect the concept back to a realistic production or interview scenario for 'How does super().__init__(...) help when a subclass overrides __init__?'

Comparison / Tradeoffs

Aspect Notes
Core idea It calls the parent class's constructor explicitly, so the subclass can add its own setup on top of the parent's initialization instead of having to duplicate the parent's logic.
Practical tradeoff It calls the parent class's constructor explicitly, so the subclass can add its own setup on top of the parent's initialization instead of having to duplicate the parent's logic.

Why

Summary

This is the standard way to build on inherited behavior rather than re-implementing it from scratch in every subclass.

Longer Answer

This is the standard way to build on inherited behavior rather than re-implementing it from scratch in every subclass. In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview.

Key Points

  • This is the standard way to build on inherited behavior rather than re-implementing it from scratch in every subclass
  • In practice, explain where this shows up in production code, what tradeoffs matter, and how you would justify the choice in an interview
  • In an interview, relate 'How does super().__init__(...) help when a subclass overrides __init__?' to implementation decisions, tradeoffs, and operational impact
  • Use the answer to connect the concept back to a realistic production or interview scenario for 'How does super().__init__(...) help when a subclass overrides __init__?'

Comparison / Tradeoffs

Aspect Notes
Core idea This is the standard way to build on inherited behavior rather than re-implementing it from scratch in every subclass.
Practical tradeoff In an interview, relate 'How does super().__init__(...) help when a subclass overrides __init__?' to implementation decisions, tradeoffs, and operational impact.

Open in the app to mark lessons complete, take notes and track your progress.