You’ve presented these two alternatives as if they would do the same thing. They won’t, and it might be instructive to play around with them to see why.
I think the main concept you are missing is how Python variables and memory are very different than C variables and memory.
In C, int varname = 17; makes varname a shorthand for a memory address. The value of varname is the bits stored at that address, interpreted as an int. Initially, the bits for 17 are stored at that address.
In Python, varname: int = 17 makes varname a name that can refer to an object somewhere in memory. In this case, it refers to the int object 17. The type is inherent in the value, not in the variable. In fact, varname = "seventeen" is then a valid thing to do, it makes varname refer to a string.
In C, p = &varname gives you a pointer to the memory location that varname is short for. That is, p is the memory address for varname. Then *p = 23 stores the bits for 23 at that address, changing the value of varname. Now varname equals 23.
In Python, p = id(varname) gives you the id (In CPython, the memory address) of the object that varname refers to. It does not tell you anything about where the varname variable is. There is no way in Python to create a reference to a variable, only to an object. There is nothing you can do with p that will change what varname means.
This is how variables are different in C and Python. One way to look at it: it’s not that Python has no pointers, it’s that in Python everything is a pointer. There’s no need to create another way to make references, because every value is already reached through a reference.
This gets at the question you haven’t yet answered: “Wherever you would store the id for later, why not just store the object?” Storing the object is storing a reference (a pointer), so you don’t need to fiddle with ids.