Two methods, two jobs
A subclassed model is a Python class that inherits from keras.Model and splits its work across exactly two methods. __init__() is the parts list: you instantiate every layer the model owns and store it on self. call() is the assembly: it receives an input tensor and threads it through those layers to produce an output. Keras takes over from there — once you've defined call(), the instance behaves like any built-in model, so compile(), fit(), evaluate(), and save() all work unchanged (see the Code block).
Why the split matters
The separation isn't stylistic. Layers created in __init__() are instantiated once when you write model = MyModel() — and their weights are tracked from that moment, which is how Keras knows what to optimize. call() runs on every forward pass, once per batch. Put a layer construction inside call() by mistake and you'll silently create fresh, untrained weights on each step; put tensor math inside __init__() and there's no tensor to operate on yet. The training argument that call() receives is what lets Dropout and BatchNormalization switch between their train-time and inference-time behavior — thread it through to every sub-layer that cares.