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!