Python In-Depth — Assigning the variable
Hello There, Let’s Learn the fundamentals of python understand the inner workings of the python and get fundamental cleared.
This journey is all about re-exploring python and its inner working. While starting, we might have missed it and went towards using framework rather appreciating the beauty of the language.
This Series expects you already know python and you are familiar with the basics, you know what it is but you might have never got time to explore the beauty or asked why and how things are done as it?
Let’s now understand how assigning a variable works in python.
The syntax that I am showing you below is familiar concept you might have used it everyday, or at-least you are aware how it works.
x = 10
A variable is created with an “assignment operator” equal sign =
, with the variable's name on the left and the value it should store on the right.
In the computer’s memory, each variable is like a box, identified by the name of the variable. In the box is a pointer to the current value for that variable.
Now think like this you have a box you write label X on it, you keep something inside that box and store it in shelf. When you want to take the item from the the box, you first look for the box label i.e. (X). When you see it you take it out from the box open the box and take out the item that you have kept.
what happens when you try to take out the thing which is not inside the box?
x = 10
print(y)
# NameError: name 'y' is not defined
exception NameError
Raised when a local or global name is not found. This applies only to unqualified names. The associated value is an error message that includes the name that could not be found.
The name
attribute can be set using a keyword-only argument to the constructor. When set it represent the name of the variable that was attempted to be accessed.
Let’s look into a bit more complex example and see a figure how things are assigned
x = 10
y = 'hello'
y = 'bye'
z = y
Okay, let’s understand it step wise, what happened here,
- The assignment
x = 10
simply setsx
to point to10
. - The assignment
y = 'hello'
setsy
to point to'hello'
. Then the liney = 'bye'
changesy
to point to'bye'
, overwriting the first pointer. Assigning a variable overwrites any existing pointer that variable had. Each assignment is like the phrase "now point to" — the variable now points to the new thing, and any previous setting is forgotten. - Assignment between two variables like
z = y
, setsz
to point to the same thing asy
. Now they both point to the same value. It does not set one variable to point to the other variable, although the code does kind of look like that.
To understand this let’s now understand by printing the address of each item.
x = 10
print(id(x))
y = 'hello'
print(id(y))
y = 'bye'
print(id(y))
z = y
print(id(z))
y = 10
print(id(z))
Output:
4308359384
4298976080
4299631584
4299631584
4299631584
Can you find the pattern here against our output? The last three variable are pointing to same memory location. In, our output as well we can see
10
bye
bye
bye
Similar pattern, so what happened?
y = 10
When You reassign y
to the integer 10
, but this doesn't affect z
because z
was assigned the value 'bye'
earlier.
print(z)
— This still prints 'bye'
, because z
holds the value that y
had when it was assigned, which was 'bye'
After you change y
to 10
, it doesn't affect the value of z
because z
had already been assigned the value 'bye'
earlier, and Python variables are references to values, not links that update automatically after assignment.
Now, Lets see the mighty Garbage Collector, how does it work when we create variable.
Garbage Collector, is a program that automatically removes unwanted data held temporarily in memory during processing.
To understand more look at the picture below:
The string 'hello'
in the example above is shown in gray. It is not needed by the code after the third line runs — no variable points to it any longer, so it cannot be used. Memory like this, which is no longer accessible, is called "garbage" in computer code. A "garbage collector" is a system that reclaims garbage memory, such as 'hello'
here, so its memory can be re-used to hold a new value. This is something Python does automatically behind the scenes. The garbage collector slows the running of the code down a little.
Let’s summarize it till now, Understand the process.
When you assign a variable in Python, you are essentially creating a reference to an object in memory. This process involves multiple concepts like names, objects, mutability, and memory management. Let’s break down the entire process:
- Objects and Values
In Python, everything is an object — whether it’s a simple integer, a list, or even a function.
- Type: Defines what kind of object it is (e.g., integer, string, list).
- Value: The data stored by the object (e.g., the number
10
or the string"hello"
). - ID: The memory address where the object is stored. You can think of this as the identity of the object.
2. Variables as Names
Unlike some other languages where variables are like boxes that store values, in Python, variables are just labels (or references) to objects.
3. Variable Assignment Process
When you assign a value to a variable in Python, it goes through the following steps:
- Evaluate the right-hand side expression to get the object.
- Bind the variable name on the left-hand side to the object produced by the expression.
4. Mutability and Immutable Objects
Python distinguishes between mutable and immutable objects.
- Immutable objects: These objects can’t be changed after they are created. Common immutable objects are:
- Integers, floats
- Strings
- Tuples
- Booleans
When you modify an immutable object, Python creates a new object and rebinds the variable to the new object.
- Mutable objects: These objects can be changed after they are created. Common mutable objects are:
- Lists
- Dictionaries
- Sets
When you modify a mutable object, you are modifying the object directly in memory without creating a new one
numbers = [1, 2, 3]
ref = numbers
ref.append(4)
5. Reference Counting and Garbage Collection
Python uses a system called reference counting to manage memory. Every object has a counter that tracks how many names (or references) point to it. When an object’s reference count drops to zero (i.e., no variable points to it anymore), Python’s garbage collector automatically frees up the memory used by the object.
6. Variable Reassignment
When you reassign a variable to a new value, Python doesn’t change the original object. Instead, it simply changes the reference of that variable to point to a new object.
7. Aliasing and Side Effects
When two or more variables reference the same mutable object, modifying the object through one of the variables affects all references to that object. This is known as aliasing.
8. Copying Objects
Sometimes you might want to avoid aliasing when working with mutable objects. You can do this by copying the object:
- Shallow copy: Creates a new object, but references the same objects inside it.
- Use
copy()
for shallow copying lists, dictionaries, etc. - Deep copy: Recursively copies all objects inside the original object. Use
copy.deepcopy()
from thecopy
module.