We, the programmers, grew up learning that the concept of variables is very important one. When asked by somebody what is a variable and what happens when we create one, assign it a value, reassign the value, delete a variable etc., we used to say this:
On the line of code of creating and assigning values to variables like this
myvar = 5
the compiler reserves the memory based on the type of the variable and store the value in that memory location. On reassigning, the value in that memory location is replaced with reassigned value and on deleting, memory is cleared and released to OS. This is pretty basic to every programmer.
In python, it is a little different, the definition of variables is very similar to definition of variables in Algebra that is simply "value of a variable varies".
Python interpreter does not implement the concept of variable the way traditional compilers handle i.e. reserving memory, issuing type specific instructions, replace the value in that reserved memory location when the variables are reassigned with differnt values etc.
So let us use better terminology "names" and "objects" when refer to variables and its values in Python. We can roughly compare names to variables and objects values of the variables.
In run-time, everything is an object. We can create an object (value) without assigning it to any name (variable). What happens when we type just a number as a line of code and send it to the Python interpreter? Let us see.
1
Here above, we just created an object (value) but we did not assign it to any variable. This proves that object (value) creation is not related to name. Objects can be assigned to variables after they are created so objects do not necessarily have to know their assigned names. However, a name has to know what object is assigned to it.
Each object has a single unique id which is a memory addrss in CPython. See the id below.
id(1)
a
Above, the interpretor assumes that a is a name and complains that it is not defined.
a = 1
Now name a is accepted since it is assigned to an object and so defined.
"a"
And above, there is no complaint because the literal "a" is an object and is created, though it does not have to be assigned to any names. So names know what object is assigned to them but objects do not necessarily have to know their assigned names. More of id.
id("a")
Above is the unique id of the literal "a" object.
Objects have attributes. Let us see explore the objects.
"a".upper
"a".upper()
Now we got new string object returned. Can we get the all attributes of this object?
dir("A")
Every object has single type. We get the type by this.
type("A")
Since the type of an object is its class, we can get the type of the object this way too.
"A".__class__
Reference: Stuart Williams - Python Epiphanies - PyCon 2018 https://www.youtube.com/watch?v=-kqZtZj4Ky0&t=498s