Pointers in python is a unknown concept. Python does not speak about pointers in any sense. The reason is unknown to us and many people out there. If you say to guess we might say it because pointers are a difficult art to learn and python is just opposite of that.

The mechanism of python is exactly like passing pointers by the value in C. Pythons moto is to for simplicity and not for speed. But it doesn’t mean we can’t implement Pointers and in python it can done through objects. Now lets understand a little about python.

Also Read: Is Python worth learning in the year 2021?

What are Pointers?

A Pointer is a variable that stores other variable addresses.  Pointers are used to store the addresses of other variables or memory items. It is a data types which stores the address of other data types. If you are familiar with C or C++, then you are familiar with what pointers are?

Whenever we create a variable or an object in a programming language, it’s stored in a particular CPU address. Whenever we output the data, it pulls from that address. **Pointers are used to store the addresses and for memory management. But, at times pointers can crash our programs. Let’s get into the details.

What is Python?

Pointers in python

Python is an interpreted, object-oriented, high-level programming language with dynamic semantics. Its high-level built in data structures, combined with dynamic typing and dynamic binding, make it very attractive for Rapid Application Development. As well as for use as a scripting or glue language to connect existing components together. Python’s simple, easy to learn syntax emphasizes readability and therefore reduces the cost of program maintenance. Python supports modules and packages, which encourages program modularity and code reuse. 

Features:

  • Open Source and Free
  • Support for GUI
  • Object-Oriented Approach
  • High-Level Language
  • Integrated by Nature
  • Highly Portable
  • Highly Dynamic

What are Objects?

Now everything we do in Python is object based. And if you find yourself here and you are new to this lets give you a few examples to show you how it is true.

## int
print(f'int:- {isinstance(int, object)}') 
## str 
print(f'str:- {isinstance(str, object)}') 
## bool 
print(f'bool:- {isinstance(False, object)}') 
## list 
print(f'list:- {isinstance(list(), object)}') 
## function 
def sample():     pass print(f'function:- {isinstance(sample, object)}')
int:- True
str:- True
bool:- True
list:- True
function:- True

Now as we already told you, you can see it by yourself. Everything in Python is object. Each object in Python consist of 3 parts

Firstly: Type

It refers to the kind of object like int, float, string, etc.

Secondly: Value

It’s the actual value of an object stored in the memory.

Lastly: Reference Count

It deals with the memory in the CPU. It represents the number of Python variables referring to a memory location.

Object data types are of two types Immutable and Mutable. And knowing the objects if they are immutable and mutable is our step towards the learning about pointers:

Pointers in python

What are immutable objects?

Immutable objects are those objects that cannot be changed once created.  Most of the commonly used data types in Python are immutable. Let’s see what that means. We can test immutable objects by id() and is,

  • id(): returns the memory address of the object.
  • is: checks whether two objects have the same memory address or not.

int() is an immutable objects let us show you with an example:

a = 7 
id(a)
1744268544 

In this you can see we have assigned the value of 7 to a. Now we cant modify the value of  x in 1744268544 memory. If we try to change it, it will create a new object. But we can add a 1 to a then lets see its address again.

a += 1 
id(a)
1744268576 

The address of a is now changed and this means that the object we created is now referring to the new address.

b = a b is a
True 

Now when we assign a=b, python does not create new objects it just makes a reference from a to b in doing so it saves memory.

What are Mutable Objects?

You can change a Mutable object even after you have created it. Python does not create a new object when you change a mutable object. Let’s go into a example for further understanding:

## list is a mutable object
nums = [1, 2, 3, 4, 5]
print("---------Before Modifying------------")
print(id(nums))
print()

## modifying element
nums[0] += 1
print("-----------After Modifying Element-------------")
print(id(nums))
print()

## appending an element
nums.append(6)
print("-----------After Appending Element-------------")
print(id(nums))
---------Before Modifying------------
2197288429320

-----------After Modifying Element-------------
2197288429320

-----------After Appending Element-------------
2197288429320

As you can see even after performing several functions on the list the address does not changes. Because the list is a mutable object. The same thing occurs when we perform other mutable objects like set or dict.

A little about Python Object model:

Variables work different in python then in C. So we should first learn how variables work in C to have a better understanding of everything.

C variables:

So, let’s take a look at how variables are executed in C which is different from python.

// C syntax not Python 
int a = 918

Now we should explain what are these syntax in the above programmming:

  • Allocates memory for the integer.
  • Assigns a value to the variable a.
  • Makes a refer to the value of 918.

If we illustrate the memory, it may look like the following.

So, here you can see that a has a memory location of 0x531. If we update the value of a. The address location of a doesn’t change.

a = 849

So now if you see the location of a is not changed in C programming language. The variable is just not the name of the values its a memory location in itself.

Now if we assign a new variable to a then unlike python, C creates a new memory location. The following code assigns a to a new variable **b.

int b = a 

Now you can see that the address of b has changed. Because C creates a new location for every object we create. After C variable now let’s go to python again.

Now the Python Names:

You can call variables in python as names.

## code in python 
a = 918

The code above will go through the following things:

  • Creates a new PyObject.
  • Sets data type as an integer for PyObject.
  • Sets the value 918 to the PyObject.
  • Creates a name as we define (a).
  • Points a to the PyObject.
  • Increments the Refer Count of PyObject from 0 to 1.

a reference memory location illustration

Pointers in python

Here a refers to the pyobject in the memory. This is completely different from the variables in C. a is not a memory location as it was in C variables.

a = 87

The above statement undergoes the following steps during execution.

  • Creates a new PyObject.
  • Sets data type as an integer for PyObject.
  • Sets the value 98 to the PyObject.
  • Points a to the new PyObject.
  • Increments the Refer Count of the new PyObject by 1.
  • Decrements the Refer Count of the old PyObject by 1.

Now with Faking Pointers in Python

As we have already discussed Pointers in python were not included. But still if you want you can use Pointers in python using several different methods.

Now let’s write a simple short program to help you understand this a little better.

// C code
void increment(int *p) {
    *p += 1;
}

As you can see here the increment function takes a pointer and you can use the value referring to other pointer variable.

// C code main function 
void main() {     
int a = 759;     
printf("%d\n", a);     
increment(&a);//& operator used to extract the address of the variable     
printf("%d\n", a); }
// Output
759
769

Now we are going to use this same function on the mutable object.

Mutable Objects:

So, we can now execute the whole of above program into python using mutable objects.

## function
def increment(p):
    p[0] += 1

if __name__ == "__main__":
    a = [759]
    increment(a)
    print(a[0])
760

As you can see we have achieved the same result also through python. The function takes an increment in the list and then increments the first elements. If we try to pass a tuple as an argument to the **increment function, we will get an error. Then it will the following error as you can down below:

if __name__ == "__main__":
    a = (759,)
    increment(a)
    print(a[0])
TypeError                                 Traceback (most recent call last)

<ipython-input-32-c3bce5df94da> in <module>()
      1 if __name__ == "__main__":
      2     a = (759,)
----> 3     increment(a)
      4     print(a[0])


<ipython-input-30-042f4c577fd9> in increment(p)
      1 ## function
      2 def increment(p):
----> 3     p[0] += 1
      4
      5 if __name__ == "__main__":


TypeError: 'tuple' object does not support item assignment

Now we will talk about Pointers in Ctype:

So by using the ctypes we can create Pointers in python. The first thing that we will do is compile a .c file containing functions which use pointers and store it. Now let’s write it together.

void increment(int *p) {
    *p += 3;
}

Just assume the name of the file is incre.c and now you can just run the following command:

$ gcc -c -Wall -Werror -fpic incre.c
$ gcc -shared -o libinc.so incre.o

So as you can see the the incre.c compiles the object in incre.o. And now the second object creates another object file and produces libinc.so to work with ctypes.

import ctypes
## make sure the libinc.so present in the same directory as this program
lib = ctypes.CDLL("./libinc.so")
lib.increment
## output 
<_FuncPtr object at 0x7f46bf6e0750>
inc = lib.increment 
## defining the argtypes 
inc.argtypes = [ctypes.POINTER(ctypes.c_int)]
inc(10)
## output
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ctypes.ArgumentError: argument 1: <class 'TypeError'>: expected LP_c_int instance instead of int

Now we have an error saying the function wants a pointer.

a = ctypes.c_int(10)

So you can see a is C variable. ctypes has a method called byref() which allows you to pass the variable reference.

inc(ctypes.byref(a)) 
a
## output 
c_int(11)

Now as you can the value of a has been incremented.

Conclusion:

So, pointers in python were myth when this blog started and now we have just completely addressed now we have given you examples of how to run pointers with C on python. Hope you find this information useful. Thank You for the read.