Pointer in Python

In Python, there are no pointers as they would be in C or C++. Instead, it abstracts the direct memory management away from the user, and you will not directly work with memory addresses and pointers. However, knowing how Python handles variables, references, and object storage can make it easier for you to grasp the concept of pointers in a Pythonic way.

1. Variables and Objects in Python

In Python, variables are references to objects. Assigning a value to a variable does not actually keep the data in the variable; it just references or points to an object, keeping that data inside of that object.

Consider the following example:

x = 10

n this case:

  • x references the integer 10.
  • The number 10 is stored in memory, and x is a reference (or pointer) to that memory location.

Now, let’s print the value and check the memory address:

x = 10
print(x)  # Output: 10
print(id(x))  # Output: some memory address, e.g., 140283645388048

Here:

  • print(x) outputs the value 10 (the value stored at the memory address x points to).
  • id(x) returns the memory address of the object x is pointing to. This address is unique for each object.

2. Immutable vs Mutable Objects

In Python, objects can be immutable or mutable. This is a concept important to understand the behavior of references.

Immutable Objects

Immutable objects, once created cannot be changed in any way. Integers and strings are prime examples of this. When you “change” an immutable object, Python merely creates a new object and alters the reference so that it refers to the new object.

Example using an immutable object (integer):

a = 5
b = a
a = 10
print(a)  # Output: 10
print(b)  # Output: 5

Explanation:

  1. Initially, both a and b represent the same integer object 5.
  2. When you assign a = 10, it makes a new integer object 10, and a now refers to that new object.
  3. b still references the original object (5), so b remains unchanged.

Here, the output would be:

10
5

Mutable Objects

The objects that are mutable are lists, dictionaries, and sets. A mutable object can be modified after it is created. All references to an object will observe changes if that object is modified because all references point to the same object.

Example using a mutable object(list) :

a = [1, 2, 3]
b = a
a.append(4)
print(a)  # Output: [1, 2, 3, 4]
print(b)  # Output: [1, 2, 3, 4]

Explanation:

  1. At first, both a and b point to the same list object [1, 2, 3].
  2. When you call a.append(4), you are directly manipulating the list object with the addition of 4.
  3. Since b points to the same list, it sees the change, and a and b both reference [1, 2, 3, 4].

Here, the output will be:

[1, 2, 3, 4]
[1, 2, 3, 4]

3. References as Pointers

In Python, variables do not store the actual object data but instead store a reference to the object. It is similar to how pointers work in languages like C.

Example with reference behavior:

x = [1, 2, 3]
y = x  # y now points to the same list object as x
x.append(4)
print(x)  # Output: [1, 2, 3, 4]
print(y)  # Output: [1, 2, 3, 4]

Explanation:

  1. x refers to a list [1, 2, 3].
  2. As when y = x, y and x point towards the same object of a list.
  3. When x.append(4) is invoked, both x and y see the change because they refer to the same list object. Thus, both print the updated list [1, 2, 3, 4].

Output:

[1, 2, 3, 4]
[1, 2, 3, 4]

4. Functions and Pass-By-Reference/Pass-By-Value

In Python, arguments to functions are passed by reference, but the behavior differs for mutable and immutable objects.

Immutable Objects (Pass-by-Value)

When you pass an immutable object (like an integer or string) to a function, the function cannot modify the original object. It behaves like pass-by-value because reassigning the variable inside the function creates a new object.

Example:

def modify(a):
    a = 10
    print("Inside function:", a)
  
x = 5
modify(x)
print("Outside function:", x)

Explanation:

  1. x is set to 5 initially.
  2. Inside the function, a is reassigned to 10 that creates a new object.
  3. The change inside the function does not change the value of x outside the function since integers are immutable.

Output:

Inside function: 10
Outside function: 5

Mutable Objects (Pass-by-Reference)

When you pass a mutable object (like a list or dictionary) to a function, any modifications inside the function will affect the original object because both the function and the caller are referring to the same object.

Example:

def modify(lst):
    lst.append(4)

my_list = [1, 2, 3]
modify(my_list)
print(my_list)  # Output: [1, 2, 3, 4]

Explanation:

  1. my_list is passed to the modify() function.
  2. Inside the function, lst.append(4) modifies the original list.
  3. Since lists are mutable, the change is reflected outside the function.

Output:

[1, 2, 3, 4]

5. ID Function (Memory Address)

The id() function in Python can be used to inspect the memory address where an object is stored. This is useful to understand how references behave.

Example:

a = [1, 2, 3]
b = a  # b points to the same list object as a
print(id(a))  # Output: some memory address, e.g., 140283645388048
print(id(b))  # Output: same memory address as a

Explanation:

  1. a and b both refer to the same list object in memory.
  2. id(a) and id(b) return the same memory address, meaning they are pointing to the same object.

Output:

140283645388048  # Example address (this will vary)
140283645388048  # Same address as a

Conclusion

While Python doesn’t allow pointer manipulation like in C/C++, the concept of references in Python is analogous. When you assign one variable to another, you’re creating a reference to the same object in memory. The behavior of immutable vs. mutable objects dictates how changes to those objects are reflected across variables that reference them.