โ๏ธ No Pointers in Python?#
To run your code in Colab, click on the rocket icon at the top of this page.
Iโve come across numerous computer science and engineering students who mistakenly believe that languages such as Java, Python, C#, and Objective-C donโt incorporate the concept of pointers. Many of them share a common sentiment, saying, โI prefer Python/Java/C# because I donโt have to deal with those tricky pointers.โ
Personally, Iโd hesitate to collaborate with individuals who hold this misconception, as their approach could potentially introduce a slew of bugs into the project.
Now, letโs delve into an example involving a list in Python.
x = [1, 2, 3, 4, 5]
print(x)
[1, 2, 3, 4, 5]
Letโs assign it to a new variable y
and change one of the elements in the list.
y = x
y[0] = 0
print(y)
[0, 2, 3, 4, 5]
Letโs see what happened to x
.
print(x)
[0, 2, 3, 4, 5]
We modified only y
, not x
. Why is x
also changed? Because x
and y
are internally pointers.
When we created the list, x
, a new list object was created and the address of the object was assigned to x
as shown below.
x
+---+
| -|-------> [1, 2, 3, 4, 5]
+---+
The variable y
is not a new copy of the list. Instead, it is a copy of the value of x
, the address of the list.
x
+---+
| -|-------> [1, 2, 3, 4, 5]
+---+ ^
|
y |
+---+ |
| -|---------+
+---+
So, when you modify y
to [0, 2, 3, 4, 5]
, the list becomes
x
+---+
| -|-------> [0, 2, 3, 4, 5]
+---+ ^
|
y |
+---+ |
| -|---------+
+---+
Then, how can we create a new copy of the list for y
? We need to use copy
in Python.
import copy
x = [1, 2, 3, 4, 5]
y = copy.copy(x)
This will create a new copy of the list as shown below
x
+---+
| -|-------> [1, 2, 3, 4, 5]
+---+
y
+---+
| -|-------> [1, 2, 3, 4, 5]
+---+
What would happen if you modify y
?
y[0] = 0
print(x)
print(y)
[1, 2, 3, 4, 5]
[0, 2, 3, 4, 5]
The list x
remains intact because x
and y
are pointing at different objects as shown below.
x
+---+
| -|-------> [1, 2, 3, 4, 5]
+---+
y
+---+
| -|-------> [0, 2, 3, 4, 5]
+---+
What if x
is a list contaning another list? Would the copy
function create a completely seprate copy of x
?
x = [1, 2, 3, 4, [5, 6, 7]]
print(x)
y = copy.copy(x)
print(y)
[1, 2, 3, 4, [5, 6, 7]]
[1, 2, 3, 4, [5, 6, 7]]
y[0] = 0
print(x)
print(y)
[1, 2, 3, 4, [5, 6, 7]]
[0, 2, 3, 4, [5, 6, 7]]
Although it creates a copy of x
, it is not a complete copy of x
.
y[4][0] = 0
print(x)
print(y)
[1, 2, 3, 4, [0, 6, 7]]
[0, 2, 3, 4, [0, 6, 7]]
Since the last element of x
is another list, x[4] is the address (pointer) of the list. So, x
and y
can be depicted as shown below.
x
+---+
| -|-------> [1, 2, 3, 4, ( )]
+---+ |
+-----------> [0, 6, 7]
^
|
y +-------------+
+---+ |
| -|-------> [0, 2, 3, 4, ( )]
+---+
Since the Python copy
function basically creates a shallow copy, x
and y
are not completely different objects.
Is there a way to create a complete copy of an object? Yes and it is called a deep copy.
x = [1, 2, 3, 4, [5, 6, 7]]
print(x)
y = copy.deepcopy(x)
print(y)
[1, 2, 3, 4, [5, 6, 7]]
[1, 2, 3, 4, [5, 6, 7]]
y[0] = 0
print(x)
print(y)
[1, 2, 3, 4, [5, 6, 7]]
[0, 2, 3, 4, [5, 6, 7]]
y[4][0] = 0
print(x)
print(y)
[1, 2, 3, 4, [5, 6, 7]]
[0, 2, 3, 4, [0, 6, 7]]
Now, x
and y
are compelely different objects and depicted as
x
+---+
| -|-------> [1, 2, 3, 4, ( )]
+---+ |
+-----------> [5, 6, 7]
y +-----------> [0, 6, 7]
+---+ |
| -|-------> [0, 2, 3, 4, ( )]
+---+
OK. Then, how come there is no notion of pointers in Python, Java, C#, and other programming languages? In the world of C/C++, variable x
can an object (structure in C) itself or a pointer to the object as shown below
x is the object itself
x
[1, 2, 3, 4, 5]
x is a pointer
x
+---+
| -|-------> [1, 2, 3, 4, 5]
+---+
For example, in the following code, point
is a structure and ptr
is a pointer to the structure.
struct Point {
int x;
int y;
};
struct Point point = {320, 200};
struct Point *ptr = &point;
point
(x = 1, y = 2)
ptr ^
+---+ |
| -|------->
+---+
Unlike C and C++, in most other programming languages like Python, Java, and C#, objects are accessed using only pointers (ptr
in the above example) because there does not exist a varible that is an object itself (point
in the above example). For example, the declaration in Java
MyClass x;
does not mean that x contains objects of type MyClass, but rather that x contains pointers to objects of type MyClass (or null). However, because it is extremely burdensome always to be saying โx contains a pointer to MyClassโ, the universal practice is just to say โx is a P.โ
Do you still think you can write code in Python/Java/C# with no clear understanding of pointers? Dude, even MATLAB has pointers!