if you write
an instance of class A is created and bound to the local identifier 'a'.
I think it perhaps better to think of the label 'a' being bound to the
object rather than vice versa. For one, a label can only be bound (stuck
to, like a stick note) to one object at a time while one object can have
many labels (and other references) stuck to it.
If you later write
the object 5 is reassigned to the same identifier,
Or one could say that the label 'a' is removed from the A() object and
reassigned to the 5 object. Since the 5 object may have numerous other
connections, and since those connections are unaffected by the new
connection to 'a', whereas the previous assignment of 'a' is broken, I
think it better to say that 'a' is being reassigned, not 5.
deleting whatever value was stored there before.
In memory-oriented languages, such as C, names refer to chunks of memory
where values are stored and deleted. Assigning a new value to a variable
puts a new value in that chunk of memory, necessarily overwriting the old.
In object-oriented Python, objects have values and possibly multiple
associations with names and slots. If, but only if, 'a' was the last
association of its last assigned-to object, then that object is eligible
for deletion.
In other words: identifiers don't have types.
This and the following I agree with.
Terry J. Reedy