# 3.7 Inheritance: Tracing Initialization

Let's trace what happens when we initialize an object
in the context of inheritance.
We'll use a fresh example about monsters:

```python
from typing import Any


class Monster:
    def __init__(self, name: str) -> None:
        self.name = name
        self.hunger = 100
        self.energy = 0

    def eat(self, item: Any) -> None:
        raise NotImplementedError

    def sleep(self, minutes: int) -> None:
        self.energy += minutes

    def __str__(self) -> str:
        return self.name + 'Boo!'


class Gremlin(Monster):
    def __init__(self, name: str) -> None:
        Monster.__init__(self, name)
        self.stuffy = 'Bunny'

    def eat(self, item: Any) -> None:
        # Eating makes Gremlins more hungry!
        self.hunger = self.hunger + 10

    def __str__(self) -> str:
        return self.name + 'Mwahaha!'


if __name__ == '__main__':
    m = Gremlin('Julius')
```

In the main block, when we call `Gremlin('Julius')` we invoke the three-step
process for creating an instance of a class:

1.  Create a new `Gremlin` object behind the scenes.
2.  Call `__init__` with the new object passed to the parameter `self`,
    along with the other argument, `'Julius'`.
3.  Return the new object (which we then assign to variable `m``, which must first be created).

Let's go through these steps.
In step 1, a new `Gremlin` object is created for us, and is currently empty.
This is the state of memory afterwards:

```{image} images/G0-crop.jpg
:alt: A stack frame for the main block and a (currently empty) Gremlin object with id106.
:width: 450px
:align: center
```

In step 2, the `__init__` method for `Gremlin` is called,
with the new object passed as the parameter `self`,
and the other argument, `'Julius'`, passed as `name`.
The `Gremlin` object is still empty.
At the moment after the `Gremlin` initializer has been called, this is the
state of memory:

```{image} images/G1-crop.jpg
:alt: The stack now include a frame for the call to Gremlin's initializer. The object is still empty.
:width: 450px
:align: center
```

If we look at the code for the `Gremlin` initializer, we see that
the first thing this method does is call the initializer for `Monster`,
passing the values of `self` and `name`.
The `Gremlin` object is still empty.

```{image} images/G2-crop.jpg
:alt: The stack now include a frame for the call to Monster's initializer. The object is still empty.
:width: 450px
:align: center
```

The `Monster` initializer has three lines of code.
It use `self` to access the new `Gremlin` object
and defines three new attributes within it, giving each a value:

```{image} images/G3-crop.jpg
:alt: The object now has three attributes inside it, which are name, hunger, and energy.
:width: 450px
:align: center
```

When the `Monster` initializer returns, we resume the `Gremlin` initializer
where we left off.
It has one line of code left, which uses `self` to access the `Gremlin` object
and put a new attribute called `stuffy` inside it:

```{image} images/G4-crop.jpg
:alt: The stack frame for Monster's initializer has been popped, and the object now also has an attribute called stuffy.
:width: 450px
:align: center
```


Finally, step 2 is done and we pop the `Gremlin` initializer call from the stack.
We are back in the `__main__` block where we were in the middle of completing
an assignment statement: `m = Gremlin('Julius')`.
We have evaluated the right-hand side, yielding the id of a `Gremlin` object, id106.
We will assign it to `m`, but since there is no `m` in the frame where we are
working, we make one first:

```{image} images/G5-crop.jpg
:alt: The stack frame for Gremlin's initializer has been popped also, and we are back to the stack frame for the main block. It contains variable m, which holds id106, the id of the new Gremlin object we just initialized.
:width: 450px
:align: center
```

A lot had to happen to execute that one-line main block!
