โ†—๏ธ No Pointers in Python?#


To run your code in Colab, click on the rocket icon at the top of this page. Colab

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!