Python is both strongly and dynamically typed.
Strongly typed: type of value doesn't change in unexpected ways. A string containing only digits doesn't magically become a number, as may happen in Perl. Every change of type requires an explicit conversion.
Dynamically typed: Runtime objects (values) have a type instead of static typing where variables have a type.
The example you mentioned works because the variable does not have a type; it can name any object. After bob=1, you'll find that type(bob) returns an int, but after bob="bob", it returns str. (Note that type is a regular function, so it evaluates its argument, then returns the type of the value.