![[Column] How to Manage Variables and Data in Python.](https://python101.tech/wp-content/uploads/2025/08/eyecatch_187.webp)
In this lecture, we will learn how Python manages variables and data.
Table of Contents(目次)
Management of Numbers/Strings
Numbers
First, let’s explain how Python manages numbers assigned to variables.
When num1 = 5
is executed, Python allocates the number 5
in memory.
num1 = 5
The number 5
is assigned the data type integer and given an id number. The id number is used by Python to uniquely identify the data in memory. The variable name "num1" acts like a label that refers to this id number, linking the variable and the value together.

Next, when num2 = 5
is executed, since the number 5
already exists, Python reuses the existing 5
and links the variable "num2" to it.
num1 = 5
num2 = 5

This method has advantages such as minimizing memory usage by referencing data without creating new data.
The same behavior occurs when num2 = num1
is executed. "num2" refers to the same value that "num1" is referencing.
num1 = 5
num2 = num1
Next, let’s see what happens when num1 = 10
is executed. Since the number 10
does not yet exist in memory, new data is created, and the reference of "num1" switches to the value 10
.
num1 = 5
num2 = 5 # or "num2 = num1"
num1 = 10

This is the basic principle of how Python manages data.
Strings
The same principle applies to strings. When you write code like the following, both variables point to the same string data with the same id number.
str1 = 'Hello'
str2 = 'Hello'
However, if strings are created in different ways, even identical sequences of characters may be treated as different data.
str1 = 'Hello'
str2 = '{}llo'.format('He') # 'Hello'
str3 = 'Hello World'[:5] # 'Hello'

In the case of strings, issues caused by differences in variable references rarely occur, but it’s still good to keep this in mind.
Summary so far
We explained how Python creates variables and data internally and manages them by linking them together.
Up to now, we’ve often used expressions like “a variable is like a box” or “assigning a value to a variable,” so you may find the difference between that image and Python’s internal behavior surprising. However, this fact only becomes important in certain cases, such as copying objects (like lists) where problems can occur. Therefore, while we’ll continue using the phrase “assign a value to a variable,” we’ll highlight these details whenever data management becomes relevant.
Basics of List Management
Now, let’s learn how lists are managed in Python.
First, let’s understand the structure of list data management.
original_list = [1, 2, 3]
When the above code is executed, a “list object” is created. A list does not directly store the actual data, but instead manages references to data by their indexes.

Strictly speaking, as shown in the figure above, data is managed by referencing each element using its index. However, this way of writing makes the explanation more complicated, so from here on, we’ll use a simpler notation as shown in the figure below.

The relationship between a list and variables with the same elements
Example of referencing the same list object
As explained so far, variables manage data by referencing list objects. If you write the code as follows, each variable will reference the same data.
original_list = [1, 2, 3]
copied_list = original_list

When you write copied_list = original_list
, both variables end up referencing the same data.
Example of referencing different list objects
However, if you create data as follows, you can create and reference a separate list that contains the same elements.
# Method of directly writing the list data
original_list = [1, 2, 3]
copied_list = [1, 2, 3]
# Even with an empty list, different data will be created
original_list = []
copied_list = []
# Method using slicing
original_list = [1, 2, 3]
copied_list = original_list[:]
# Method using the copy() method
original_list = [1, 2, 3]
copied_list = original_list.copy()
The first method is to directly write the list or its elements when assigning to copied_list
. Even if the contents of the elements are exactly the same, directly written lists will be generated as different data, and each variable will reference separate data. This is also true for empty lists ([]
).

The second method is using slicing. Slicing extracts the specified range of elements and creates new data. This applies even when extracting the entire range ([:]
).
The third method is using the copy()
method.
If you want to create and reference a separate list with the same elements, you can choose from the three methods above.
Be sure to distinguish this from the method where both variables reference the same list.
Why editing the copied list also changes the original list
Now let’s look at the main topic: why editing the copied list also changes the original list.
When you write copied_list = original_list
, both variables reference the same list. After that, if you edit an element such as copied_list[0] = 99
, Python doesn’t check whether that list is also referenced by another variable. Instead, it simply performs the action of “editing the element of the list that copied_list is referencing.”
original_list = [1, 2, 3]
copied_list = original_list
copied_list[0] = 99
print(original_list) # [99, 2, 3]
print(copied_list) # [99, 2, 3]

When the lists are printed at the end, the information of the list each variable is referencing is displayed, so the modified [99, 2, 3]
is shown.
Editing lists copied with slicing or copy()
When you use slicing ([:]
) or the copy()
method, a new list is created and each variable references a different list. Therefore, even if you edit an element such as copied_list[0] = 99
, the list referenced by the other variable is not affected.
original_list = [1, 2, 3]
copied_list = original_list[:] # or "original_list.copy()"
copied_list[0] = 99
print(original_list) # [1, 2, 3]
print(copied_list) # [99, 2, 3]

Managing Nested Lists
So, what happens when a list is nested? Unfortunately, using slicing ([:]
) or the copy()
method cannot solve certain issues. Let’s look at the problems with nesting and how to resolve them step by step.
Basics of Managing Nested Lists
First, let’s check how nested data is managed.
original_list = [[1, 2]]

When the above code is executed, both the outer and inner lists are created. As shown in the diagram, the list with id: 0000006
manages the list with id: 0000007
as the element at index [0]
.
Next, let’s see the behavior when duplicating a list using slicing ([:]
).
original_list = [[1, 2]]
copied_list = original_list[:]

When slicing is used, the list directly referenced by "original_list" is duplicated. As shown in the diagram, the list referenced by "copied_list" is different from the one referenced by "original_list". However, the list (id: 0000008
) still references the list with id: 0000007
at index [0]
.
In other words, when slicing is used, the "inner" list is not duplicated. Instead, both variables share the reference to the list at index [0]
of the outer list. The same applies when using the copy()
method.
Editing a Nested List
Next, let’s edit a nested list and check its behavior.
The following code modifies copied_list[0][0]
.
original_list = [[1, 2]]
copied_list = original_list[:]
copied_list[0][0] = 99
print(original_list) # [[99, 2]]
print(copied_list) # [[99, 2]]
When this code is executed, both output [[99, 2]]
.
This happens because the list referenced by copied_list[0]
is the same as the one referenced by original_list[0]
. Therefore, modifying the element in that list (id: 0000007
) affects the outputs of both variables.

Shallow Copy and Deep Copy
Shallow Copy
Now, let’s explain the term Shallow Copy. A Shallow Copy duplicates only the "outer" object (such as a list or other data structure) while keeping the same references for any nested objects. In other words, slicing ([:]
) and the copy()
method perform a Shallow Copy.
The advantage of a shallow copy is that only the outer object is duplicated, so memory usage and processing speed are not heavily impacted. The drawback is that since nested objects are shared with the original, you must be careful when modifying their elements.
Deep Copy
A Deep Copy duplicates not only the outer object but also all nested structures, creating a completely independent copy. This ensures that editing a nested list does not affect the other. The drawback is that when copying large amounts of data, memory usage and processing speed can be impacted.
In Python, you can use the copy module’s deepcopy()
function to duplicate data, including nested structures.
import copy
original_list = [[1, 2]]
copied_list = copy.deepcopy(original_list)
copied_list[0][0] = 99
print(original_list) # [[1, 2]]
print(copied_list) # [[99, 2]]
To use the deepcopy()
function, first import the copy module.
Then, after defining "original_list", run copied_list = copy.deepcopy(original_list)
to duplicate the list, including its nested lists. As shown in the diagram, both the directly referenced list and the list referenced as its element are duplicated.

After performing a deepcopy, running copied_list[0][0] = 99
edits the nested list element without affecting the original.

The output shows "original_list" as [[1, 2]]
and "copied_list" as [[99, 2]]
, confirming that edits can be made without changing the other list.