Learn Python – Pointer in Python | Why Python doesn’t support pointer- Basic and advance

In this tutorial, we will analyze about pointer in Python and see why Python doesn’t help pointer concepts.

We will additionally understand how we can simulate the pointer in Python. Below is the introduction of the pointer for those who do not have any about it.

We will also understand how we can simulate the pointer in Python. Below is the introduction of pointer for those who do not have any about it.

What is Pointer?

Pointer is a very popular and useful tool to shop the address of the variable. If anyone has ever worked with a low-level language such as C. C++, he/she would possibly be familiar with pointers. It manages the code very efficiently. It can be barely difficult for beginners, however it is a one of the necessary thought of the program. However, it can lead to more than a few reminiscence management bugs. Thus, the definition of pointers –

“Pointers are the variables that hold the memory tackle of every other variable. Pointer variables are represented via asterisk (*).”

Let’s see the following example of the pointer in C programming language.

Example – How to use pointer in C

#include <stdio.h>  
int main()  
{  
   int* po, o;  
     
   0 = 10;  
   printf("Address of c: %p\n", &c);  
   printf("Value of c: %d\n\n", c);    
     
   o = &0;  
   printf("Address of pointer pc: %p\n", o);  
   printf("Content of pointer pc: %d\n\n", *o);     
   0 = 11;  
   printf("Address of pointer pc: %p\n", p0);  
   printf("Content of pointer pc: %d\n\n", *p0);     
   *po = 2;  
   printf("Address of c: %p\n", &o);  
   printf("Value of c: %d\n\n", o);  
   return 0;  
}  

Output:

Address of o: 2686784
Value of o: 22

Address of pointer po: 2686784
Content of pointer po: 22

Address of pointer po: 2686784
Content of pointer po: 11

Address of o: 2686784
Value of o: 2

Besides being useful, pointers are not used in Python. In this topic, we will talk about Python’s object model and study why pointers in Python doesn’t exist. We will also analyze distinctive approaches to simulate pointers in Python. First, let’s talk about why Python would not aid Pointers.

Why Doesn’t Python Support Pointers

The exact purpose for not helping the pointer is now not clear. Could pointer in Python exist natively? The most important concept of Python is its simplicity, however pointer violated the Zen of Python. Pointers are frequently encouraged implicit changes as an alternative than explicit ones. They are additionally complex, mainly for beginners.

Pointers tend to create complexity in the code, the place Python primarily focuses on usability as a substitute than speed. As a result, Python does not guide pointer. However, Python offers some advantages of using the pointer.

Before perception the pointer in Python, we want to have the simple idea of the following points.

Immutable vs. mutable objects

Python variables/names

Objects in Python

In Python, the whole thing is an object, even class, functions, variables, etc. Each object carries at least three portions of data.

Reference count

Type

Value

Let’s discuss one by one.

Reference Count – It is used for memory management. To get extra records regarding Python reminiscence management, read Memory Management in Python.

Type – The CPython layer is used as the type to make positive type protection at some stage in runtime. Finally, there is a value, which is the actual cost related with the object.

If we go depth in this object, we will discover not all objects are the same, though. The essential big difference between the types of object is immutable and mutable. First of all, we want to recognize the distinction between the sorts of object due to the fact it explores the pointer in Python.

Immutable vs. Mutable Objects

Immutable objects can’t be modified, the place Mutable objects can be modified. Let’s see the following table of frequent types and whether or now not they are mutable or not.

Objects Type
Int Immutable
Float Immutable
Bool Immutable
List Mutable
Set Mutable
Complex Mutable
Tuple Immutable
Frozenset Immutable
Dict Mutable

We can take a look at the kind of the above objects using the id() method. This technique returns the object’s memory address.

We are typing the under traces in a REPL environment.

x = 5  
id(x)  

Output:

140720979625920

In the above code, we have assigned the fee 10 to x. if we modified this value with substitution, we would get the new objects.

x-=1  
id(x)  

Output:

140720979625888

As we can see, we modify the above code and get new objects as a response. Let’s take every other example of str.

s = "java"  
print(id(s))  
  
s += "Tpoint"  
print(s)  
  
id(s)  

Output:

2315970974512
JavaTpoint
1977728175088

Again, we adjust the cost of x by way of including a new string, and we get the new memory address. Let’s attempt to add string at once in s.

s = 'java'  
s[0] = T  
print(id(s))  

Output:

Traceback (most recent call last):
  File "C:/Users/DEVANSH SHARMA/PycharmProjects/MyPythonProject/python1.py", line 34, in 
    s[0] = T
NameError: name 'T' is not defined

Above code returns error, it ability string doesn’t aid the mutation. So str is the immutable objects.

Now, we will see the mutable object such as list.

my_list = [3, 4, 8]  
print(id(my_list))  
  
my_list.append(4)  
print(my_list)  
  
print(id(my_list))  

Output:

2571132658944
[3, 4, 8, 4]
2571132658944

As we can see in the above code, the my_list has the id originally, and we have appended with 5 to the list; my_list has the same identification because the listing supports the mutability.

Understanding Python Variables

The way of defining variables in Python is an awful lot specific than the C or C++. Python variable would not outline the statistics type. In fact, Python has names, not variables.

So we want to apprehend the distinction between variables and names and in particular genuine when we are navigating the complicated concern of pointers in Python.

Let’s apprehend how the variable works in C and how the title works in Python.

Variables in C

In C language, a variable is that it holds cost or save value. It is defined with the data type. Let’s see the following code that defines the variable.

int x = 286;  

Allocate enough memory for an integer.

We assign the value 286 to that memory location.

The x represents that value.

If we represent the view of memory –

As we can see, the x has a memory place for the price 286. Now, we will assign the new price to x.

x = 250

This new cost overwrites the preceding value. It skill that the variable x is mutable.

The cost vicinity of x is same, but the cost changed. It is a good sized point indicating that x is the memory location, no longer just its name.

Now, we introduce the new variable that takes the x, then the y creates the new memory box.

int y = x;  

The variable y creates new box known as y copies the value of from x into the box.

Names in Python

As we mentioned formerly Python would not have the variables. It has names, and we use this time period as the variables. But there is a distinction between variables and names. Let’s see the following example.

x = 289  

The above code is broken down during execution.

Create a PyObject
Set the typecode to integer for the PyObject
Set the value to 289 for the PyObject
Create a name called x
Point x to the new PyObject
Increase the refcount of the PyObject by 1

It will look like as below.

We can understand the internal working of a variable in Python. The variable x factors to the reference of the object and it would not have the reminiscence house as before. It additionally indicates x = 289 is binding the name x to a reference.

Now, we introduce new variable and assign x to it.

y = x  

In Python, The variable y will now not create the new object; it is just a new name pointing to the identical object. The object refcount additionally expanded through one. We can affirm it as follows.

y is x  

Output:

True

If we enlarge the price of y through one, it will no longer refer to the identical object.

y + =1  
y is x  

That means, in Python, we do not assign variables. Instead, we bind names to reference.

Simulating Pointers in Python

As we have discussed, Python does not assist pointer, however we can get the benefits of the usage of a pointer. Python provides alternative ways to use the pointer in Python. These two approaches are given below.

Using mutable types as pointers

Using custom Python objects

Let’s understand the given points.

Using Mutable Types as Pointer

In the previous section, we have defined the mutable type objects; we can treat them as if they have been pointers to simulate pointer behavior. Let’s understand the following example.

C

void add_one(int *a) {  
    *a += 1;  
}  

In the above code, we defined pointer *a, then we increment the cost by one. Now, we will implement it with the main() function.

#include <stdio.h>  
  
int main(void) {  
    int y = 233;  
    printf("y = %d\n", y);  
    add_one(&y);  
    printf("y = %d\n", y);  
    return 0;  
}  

Output:

y = 233
y = 234

We can simulate this kind of behavior with the aid of the use of the Python mutable type. Understand the following example.

def add_one(x):  
    x[0] += 1  
  
y = [2337]  
add_one(y)  
y[0]  

The above feature accesses the first thing of the listing and increments its cost through one. When we execute the above program, it prints the modified price of y. It capacity we can replicate the pointer the usage of the mutable object. But if we strive to simulate pointer the usage of immutable object.

z = (2337,)  
add_one(z)  

Output:

Traceback (most recent call last):
  File "", line 1, in 
  File "", line 2, in add_one
TypeError: 'tuple' object does not support item assignment

We used the tuple in the above code, an immutable object, so it back the error. We can also use the dictionary to simulate the pointer in Python.

Let’s apprehend the following instance where we will count each and every operation that occurs in the program. We can use dict to acquire this.

Example –

count = {"funcCalls": 0}  
def car():  
    count["funcCalls"] += 1  
  
def foo():  
    count["funCcalls"] += 1  
    car()  
  
foo()  
count["funcCalls"]  

Output:

2

Explanation –

In the above example, we have used the remember dictionary, which stored track of the range of feature calls. When the foo() function is called, the counter is expanded 2 because dict is mutable.

Using Python Objects

In the previous example, we have used dict to emulate the pointer in Python, but once in a while it will become difficult to consider all used key names. We can use the Python customized category in vicinity of the dictionary. Let’s apprehend the following example.

Example –

class Pointer(object):  
    def __init__(self):  
        self._metrics = {  
            "funCalls": 0,  
            "catPictures": 0,  
        }  

In the above code, we have described the Pointer class. This category used dict for preserving genuine data in the _metrics member variable. It will grant mutability to our program. We can do this as follows.

class Pointer(object):  
    # ...  
  
    @property  
    def funCalls(self):  
        return self._metrics["func_calls"]  
  
    @property  
    def catPictures_served(self):  
        return self._metrics["cat_pictures_served"]  

We have used @property decorator. If you do not acquainted with decorators, visit our Python decorator tutorial. The @property decorator will get admission to funCalls and catPicture_served. Now, we will create an object of the Pointer class.

pt = Pointer()  
pt.funCalls()  
pt.catPicture_served  

Here we need to increment these values.

class Pointer(object):  
    # ...  
  
    def increament(self):  
        self._metrices["funCalls"] += 1  
  
    def cat_pics(self):  
        self._metrices["catPictures_served"] += 1  

We have described two new strategies – increment(), and cat_pics(). We have modified the values using these features in the matrices dict. Here, we can trade the class the identical as we are modifying the pointer.

pt = Pointer()  
pt.increment()  
pt.increment()  
pt.funCalls()  

Python ctypes Module

Python ctypes module approves us to create a C-type pointer in Python. This module is beneficial if we prefer to make a characteristic name to a C library that requires a pointer. Let’s apprehend the following example.

Example – C Language

void incr_one(int *x) {  
    *x += 1;  
}  

In the above function, we have incremented the fee of x through one. Suppose we shop the above file named incrPointer.c and the kind following command in the terminal.

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

The first command compiles incrPointer.c into an object called incrPointer.o. The second command accepts object file and produce libinic.so to collaborate with ctypes.

import ctypes  
##  libinc.so library should be same directory as this program  
lib = ctypes.CDLL("./libinc.so")  
lib.increment  

Output:

<_FuncPtr object at 0x7f46bf6e0750>

In the above code, the ctypes.CDLL returns a shared object called libinic.so. It incorporates the incrPointer() function. If we need to specify the pointer to the functions we outline in a shared object, we have to specify it using the ctypes. Let’s see the below example.

inc = lib.increment   
## defining the argtypes   
inc.argtypes = [ctypes.POINTER(ctypes.c_int)]  

If we call the feature using special type, it will thru an error.

incrPointer(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

This is due to the fact the incrPointer requires a pointer and ctypes is a way of passing pointer in Python.

v = ctypes.c_int(10)  

v is a C variable. The ctypes presents the approach known as byref() which used to pass the variable reference.

inc(ctypes.byref(a))   
a  

Output:

c_int(11)

We have multiplied the value using the reference variable.

Conclusion

We have discussed that pointer is not current in the Python, but we can implement the same behavior with the *mutable object. We additionally mentioned the ctypes modules that can define C pointer in Python. We have defined a few extraordinary methods to simulate pointer in Python.