Concepts / Defining Your Own Classes

Defining Your Own Classes

Objects follow a predictable lifecycle: construction (via __init__), operation (via method calls that modify state), and destruction (via __del__).

  • Programming
Interactive lab

Try it: Classes, Instances and Attributes

How a class creates instances with __init__ and self, why an attribute read checks the instance's __dict__ before the class, why assigning through an instance never changes the class, how a class-level list is shared by every instance, and why obj.method(x) is Class.method(obj, x).

How it works

  1. Dog(...) makes a new, empty instance and calls Dog.__init__(new_object, ...); self.name = ... stores into that object's __dict__.
  2. Reading obj.attr looks in obj.__dict__ first, then in the class.
  3. Assigning obj.attr = value always writes obj.__dict__, so it shadows a class attribute for that one object only.
  4. Mutating a class-level list (self.tricks.append) changes the one list every instance shares.
  5. obj.method is found on the class and bound to obj, so obj.method(x) runs Class.method(obj, x).

Default run (30 steps): Ready: class Dog and the statements you picked. Watch where each attribute is found and where each assignment writes. … Finished. Printed: ['sit'] / Wolf / Canis familiaris / Fido is 5.

Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. Object numbers are illustrative, not real id() values.

Educational simulation

Loading the simulation…

From Creation to Cleanup

An object-oriented program becomes easier to understand when you follow an object's lifecycle. The central pattern has three phases: construction, operation, and destruction. During construction, __init__ sets up the object's internal data attributes. During operation, methods are called with dot notation and may change the object's internal state. During destruction, Python calls __del__ to clean up the object.

Construction__init__ sets up dataattributesOperationMethods modify internalstateDestruction__del__ cleans up theobjectobject is usedobject is no longer needed
What happens to an object, and in what order, from creation through use to cleanup?

Construction with __init__

The constructor is named __init__. Python calls it automatically when you create an object. Its role is to set up the object's internal data attributes, giving the object the initial structure it needs before methods operate on it.

Object created__init__automatic callInternal dataattributesinitial setupcreation invokessets up
What changes during initialization as __init__ prepares an object's internal data?
Code walkthrough
class Counter:
    def __init__(self):
        self.value = 0

counter = Counter()
  1. 1
    The class definition describes a Counter object.
  2. 2
    The __init__ method is the constructor.
  3. 3
    The assignment inside __init__ sets up the object's internal value attribute.
  4. 4
    Creating Counter() automatically invokes __init__.

Methods and State Changes

Methods are functions that belong to objects. They are called with dot notation, such as object.method(). A method can modify the object's internal state, so the same object can contain different values after successive operations.

value0increment()method callvalue1object stateupdates
How does a method call change values stored inside the same object over time?
python
Worked example

Tracing Two Method Calls

Determine how the internal value changes in the Counter example.

  1. 1
    Create the object

    Counter() invokes __init__, which sets value to 0.

  2. 2
    First increment

    counter.increment() invokes the method, which changes value from 0 to 1.

  3. 3
    Second increment

    The same method changes the same object's value from 1 to 2.

Result

After the two method calls, the object's internal value is 2.

The important point is that counter.increment() is not just a label for an action. Python looks up the increment method on counter, calls it, and allows that method to modify the object's internal state.

Bracket Access and __getitem__

Square bracket access is another form of method invocation. For an object named stuff, the expression stuff[0] is shorthand for stuff.__getitem__(0). The source also identifies list.__getitem__(stuff, 0) as an equivalent form. In each form, the object is accessed with the key or index 0.

stuffobject[0]index__getitem__methodselected itemaccessshorthand forreturns
How does object[key] translate into a call to __getitem__, and what data flows through that call?
Written formUnderlying form
stuff[0]stuff.__getitem__(0)
stuff.__getitem__(0)direct call to the object's __getitem__ method
list.__getitem__(stuff, 0)equivalent list method form

The three equivalent forms identified in the source

python
Output
In the example, item_a, item_b, and item_c each refer to the item selected with index 0.

Reading Each Line Mechanically

When reading object-oriented code, replace surface syntax with the mechanism it represents. Creating list() invokes construction and automatic initialization. Calling stuff.append('item') looks up the append method on stuff and calls it with the supplied parameter; the method changes the list's internal state. Reading stuff[0] means recognizing the shorthand call to __getitem__(0). When the object is no longer needed at program end, Python calls __del__ for cleanup.

list()object creation__init__initializes datastuff.append('item')method callInternal statemodifiedstuff[0]bracket syntax__getitem__(0)item access__del__destructioninvokesmodifiestranslates toeventually reaches
Which Python mechanism is invoked by each line of object-oriented code?
Worked example

A Complete Trace

Map each operation in a short list example to its underlying mechanism.

  1. 1
    stuff = list()

    A list object is created, and its constructor initializes the object's internal structure.

  2. 2
    stuff.append('item')

    Python looks up append on stuff, calls it with item, and the method modifies the list's internal state.

  3. 3
    stuff[0]

    The bracket expression is shorthand for stuff.__getitem__(0), which accesses the item at index 0.

  4. 4
    Program completion

    When stuff is no longer needed at the end of the program, Python calls __del__ to perform cleanup.

Result

The visible syntax is a compact way to express construction, method-based state changes, item access, and destruction.

What do you think happens?

What mechanism does stuff[0] represent?

  • A direct call to __init__

  • A shorthand call to stuff.__getitem__(0)

  • A call to __del__

  • A method call that always changes the object's state

Reveal answer
Answer:

A shorthand call to stuff.__getitem__(0)

Square bracket syntax is defined as a shorthand for calling the object's __getitem__ method with the supplied key or index.

Mistakes in Lifecycle Tracing

  • Common mistake

    Treating __init__ as an ordinary method that must be called manually after every object is created

    What it looks like
    obj = SomeClass(); obj.__init__()
    Why it fails

    The constructor is called automatically when the object is created.

    Do this instead

    Read the creation expression as the event that invokes __init__.

  • Common mistake

    Assuming a method call only produces an action and does not change the object

    What it looks like
    stuff.append('item')
    Why it fails

    Methods can modify the object's internal state.

    Do this instead

    Record the object's state before and after each method call.

  • Common mistake

    Thinking stuff[0] is unrelated to __getitem__

    What it looks like
    item = stuff[0]
    Why it fails

    Square bracket syntax is a shorthand for stuff.__getitem__(0).

    Do this instead

    Translate bracket access into the corresponding __getitem__ call while tracing.

  • Common mistake

    Stopping the lifecycle trace after the final visible operation

    What it looks like

    The trace ends immediately after the last method call.

    Why it fails

    The lifecycle also includes destruction, during which Python calls __del__ when the object is no longer needed.

    Do this instead

    Include cleanup as the final phase of the lifecycle.

MEDIUM

For each expression below, name the underlying mechanism it invokes: creating an object with list(), changing it with append(), and accessing an item with [0]. Then place those operations in the construction, operation, or destruction phase.

Hints
  • Creation invokes the constructor and initialization.
  • A method call can modify internal state.
  • Bracket access maps to __getitem__.

Lifecycle Checklist

  1. 1
    Object construction automatically invokes __init__, which sets up internal data attributes.
  2. 2
    Methods belong to objects, are called with dot notation, and can modify internal state.
  3. 3
    Square bracket syntax such as stuff[0] is shorthand for stuff.__getitem__(0).
  4. 4
    A complete trace includes construction, operation, and destruction.
  5. 5
    When an object is no longer needed at program completion, Python calls __del__ for cleanup.

Key Takeaways

  • An object follows a lifecycle of construction, operation, and destruction.
  • __init__ is called automatically during object creation to establish internal data attributes.
  • Method calls made with dot notation can change the object's internal state.
  • stuff[0], stuff.__getitem__(0), and list.__getitem__(stuff, 0) are equivalent forms identified in the source.
  • To understand object-oriented code, map each visible expression to the mechanism it invokes.

Related concepts

More concepts starting with D