Names and objects are two different things
In Python, names and objects are two different entities. This is unlike C or C++, where a variable is a named region of storage. When we declare a variable in C, say int count = 5;, the compiler reserves a block of memory, the name count refers to that block, and the value 5 is written into it. Assigning a new value later overwrites the contents of the same block. The name and the storage are welded together for the lifetime of the variable.
Python does not work this way. When we write count = 5, two separate things happen. First, an integer object with the value 5 comes into existence, managed by the Python runtime on the heap. Second, the name count is recorded in the current namespace as referring to that object. The name is only an entry in a table of bindings. It has no type of its own, it occupies no storage for the value, and it carries no address that we could point at. The type and the value belong entirely to the object.
This has an immediate consequence. Since a name is only a binding, it can be moved. Writing count = "five" afterwards does not overwrite any storage. It creates a string object and rebinds the name count to it. The integer object 5 is simply left behind, and if nothing else refers to it, the runtime is free to reclaim it. The reverse is also true: one object can have several names bound to it at the same time. The following program demonstrates both points.
Example 1: Two names bound to one list object
names_and_objects.py
def main():
readings = [98.4, 98.7, 99.1]
alias = readings
print(readings is alias) # True
print(id(readings) == id(alias)) # True
alias.append(99.4)
print(readings) # [98.4, 98.7, 99.1, 99.4]
alias = [0.0]
print(readings) # [98.4, 98.7, 99.1, 99.4]
print(readings is alias) # False
if __name__ == "__main__":
main()
The assignment alias = readings does not copy the list. It attaches a second name to the same list object, which the is check and the matching id() values confirm. The built-in id() returns an integer that identifies the object for its lifetime, and in CPython it is the object’s memory address. Because both names refer to one object, the append() through alias is visible through readings as well. There is only one list.
The last two statements show rebinding. The assignment alias = [0.0] creates a new list and moves the name alias onto it. The name readings has not moved, so it still refers to the original list with four elements. Nothing was copied and nothing was overwritten at any point in this program. Every assignment either created a binding or moved one.
Once this distinction is clear, several Python behaviors that puzzle newcomers stop being puzzling. Passing an argument to a function binds the parameter name to the caller’s object rather than copying it. Assigning one variable to another shares an object rather than duplicating it. The del statement removes a name, not the object it refers to. Each of these is the same rule seen from a different angle: names bind, objects live on the heap, and the two are managed separately.

Discover more from Tech For Talk
Subscribe to get the latest posts sent to your email.
Leave a Reply