2.1.2 · D3OOP Fundamentals

Worked examples — `__init__` constructor — initializing attributes

3,942 words18 min readBack to topic

The scenario matrix

Before solving anything, let's enumerate every kind of input a constructor can face. Each row is a "cell". Every worked example below is tagged with the cell it covers, so you can see the whole space is filled.

Cell Situation What can go wrong / be special
A All args supplied, plain copy nothing — the baseline
B Some args omitted → immutable default default evaluated once, but immutable so safe
C Some args omittedmutable default the shared-list trap
D Computed attribute at init time derived value, no matching parameter
E Invalid input (out of range / wrong type) must reject before object exists
F Degenerate/zero input (empty, 0, None) valid but edge-case; must not crash
G __init__ chaining (super().__init__) parent must also fill its parts
H Real-world word problem translate English → attributes
I Exam twist (__init__ returns / no self.) the trap questions
J Keyword-only args (*, unit) caller must name the argument
K Varargs (*args, **kwargs) flexible arity, collect extras
L Wrong arity (too many/few args) Python raises TypeError automatically

Reading the matrix figure

The figure below draws the matrix as a factory belt, so you can see the whole space of inputs at once. Read it left to right:

  • Orange arrow (left): the raw arguments arrive on the belt — this is whatever the caller passes inside Cls(...).
  • Violet box (middle): the __init__ station bolts those arguments onto self, the fresh blank object.
  • Magenta arrow (right): the finished, filled object rolls off — that's what the caller finally receives.
  • Twelve coloured chips along the belt: one chip per cell (labelled A through L). Each chip corresponds to exactly one worked example below. The figure's whole job is to show that the twelve chips tile the entire belt with no gaps — every situation a constructor can meet is a chip, and every chip is solved below.
Figure — `__init__` constructor — initializing attributes

Every example downstream names its chip (e.g. "Cell A"), so you can always trace an example back to its place on this belt.


Worked Examples

Cell A — All arguments supplied (the baseline)


Cell B — Omitted argument, immutable default


Cell C — Omitted argument, mutable default (the trap)


Cell D — Computed attribute at init time


Cell E — Invalid input, reject before the object exists


Cell F — Degenerate / zero input (valid but edgy)


Cell G — __init__ chaining with super()


Cell H — Real-world word problem


Cell I — Exam twist (the trap questions)


Cell J — Keyword-only arguments


Cell K — Varargs (*args, **kwargs)


Cell L — Wrong arity (too many / too few arguments)


Cell coverage check

Recall Did we fill every cell?

A ::: Cell A (Point) · plain copy B ::: Cell B (Account) · immutable default C ::: Cell C (Cart) · mutable default trap + fix D ::: Cell D (Circle) · computed attribute E ::: Cell E (Temperature) · validation F ::: Cell F (Stats) · empty/degenerate input G ::: Cell G (Dog) · super() chaining H ::: Cell H (BankAccount) · word problem I ::: Cell I(a) missing self + I(b) illegal return J ::: Cell J (Distance) · keyword-only argument K ::: Cell K (Playlist) · *args and **kwargs L ::: Cell L (Pair) · wrong arity raises TypeError


Connections

  • Parent — Hinglish version
  • OOP Fundamentals — the chapter these examples live in.
  • self and instance attributes — why every example writes self.x.
  • __new__ vs __init__ — why validation aborts after the shell exists (Cell E).
  • Class vs Instance Attributes — the SETUP_FEE in Cell H.
  • Properties and computed attributes — alternative to Cell D's frozen area.
  • Mutable default argument pitfall — the Cell C disaster in depth.
  • Dunder methods__init__ is one of many.