Dans ce didacticiel, nous découvrirons le pointeur en Python et verrons pourquoi Python ne prend pas en charge les concepts de pointeur.
Nous comprendrons également comment simuler le pointeur en Python. Vous trouverez ci-dessous l'introduction du pointeur pour ceux qui n'en connaissent pas.
Nous comprendrons également comment simuler le pointeur en Python. Vous trouverez ci-dessous l'introduction du pointeur pour ceux qui n'en connaissent pas.
Qu’est-ce que le pointeur ?
Le pointeur est un outil très populaire et utile pour stocker l'adresse de la variable. Si quelqu'un a déjà travaillé avec un langage de bas niveau tel que C . C++ , il/elle serait probablement familier avec les pointeurs. Il gère le code de manière très efficace. Cela peut être un peu difficile pour les débutants, mais c'est l'un des concepts importants du programme. Cependant, cela peut entraîner divers bugs de gestion de la mémoire. Ainsi, la définition des pointeurs -
'Les pointeurs sont les variables qui contiennent l'adresse mémoire d'une autre variable. Les variables de pointeur sont représentées par un astérisque (*).'
Voyons l'exemple suivant du pointeur en langage de programmation C.
Exemple - Comment utiliser le pointeur en C
#include int main() { int* po, o; 0 = 10; printf('Address of c: %p ', &c); printf('Value of c: %d ', c); o = &0; printf('Address of pointer pc: %p ', o); printf('Content of pointer pc: %d ', *o); 0 = 11; printf('Address of pointer pc: %p ', p0); printf('Content of pointer pc: %d ', *p0); *po = 2; printf('Address of c: %p ', &o); printf('Value of c: %d ', o); return 0; }
Sortir:
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
En plus d'être utiles, les pointeurs ne sont pas utilisés dans Python . Dans cette rubrique, nous discuterons du modèle objet de Python et découvrirons pourquoi les pointeurs en Python n'existent pas. Nous apprendrons également différentes manières de simuler des pointeurs en Python. Voyons d’abord pourquoi Python ne prend pas en charge les pointeurs.
Pourquoi Python ne prend-il pas en charge les pointeurs
La raison exacte pour laquelle le pointeur n’est pas pris en charge n’est pas claire. Le pointeur en Python pourrait-il exister nativement ? Le concept principal de Python est sa simplicité, mais le pointeur a violé les Zen de Python. Les pointeurs encouragent principalement les changements implicites plutôt que les changements explicites. Ils sont également complexes, surtout pour les débutants.
Les pointeurs ont tendance à créer de la complexité dans le code, où Python se concentre principalement sur la convivialité plutôt que sur la vitesse. Par conséquent, Python ne prend pas en charge le pointeur. Cependant, Python offre certains avantages liés à l'utilisation du pointeur.
Avant de comprendre le pointeur en Python, nous devons avoir une idée de base des points suivants.
- Objets immuables ou mutables
- Variables/noms Python
Objets en Python
En Python, tout est objet, même la classe, les fonctions, les variables, etc. Chaque objet contient au moins trois éléments de données.
commande cp sous Linux
- Nombre de références
- Taper
- Valeur
Discutons-en un par un.
Nombre de références - Il est utilisé pour la gestion de la mémoire. Pour obtenir plus d’informations sur la gestion de la mémoire Python, lisez Gestion de la mémoire en Python.
Taper - Le CPython La couche est utilisée comme type pour garantir la sécurité du type pendant l'exécution. Enfin, il existe une valeur, qui est la valeur réelle associée à l'objet.
Si nous approfondissons cet objet, nous constaterons cependant que tous les objets ne sont pas identiques. La distinction importante entre les types d'objets est immuable et mutable. Tout d’abord, nous devons comprendre la différence entre les types d’objets car ils explorent le pointeur en Python.
Objets immuables ou mutables
Les objets immuables ne peuvent pas être modifiés, alors que les objets Mutable peuvent être modifiés. Voyons le tableau suivant des types courants et s'ils sont mutables ou non.
Objets | Taper |
---|---|
Int | Immuable |
Flotter | Immuable |
Booléen | Immuable |
Liste | Mutable |
Ensemble | Mutable |
Complexe | Mutable |
Tuple | Immuable |
Ensemble congelé | Immuable |
Dicté | Mutable |
Nous pouvons vérifier le type des objets ci-dessus en utilisant le identifiant() méthode. Cette méthode renvoie l'adresse mémoire de l'objet.
Nous tapons les lignes ci-dessous dans un environnement REPL.
x = 5 id(x)
Sortir:
140720979625920
Dans le code ci-dessus, nous avons attribué la valeur 10 à x. si nous modifiions cette valeur avec substitution, nous obtiendrions les nouveaux objets.
x-=1 id(x)
Sortir:
140720979625888
Comme nous pouvons le voir, nous modifions le code ci-dessus et obtenons de nouveaux objets en réponse. Prenons un autre exemple de str .
s = 'java' print(id(s)) s += 'Tpoint' print(s) id(s)
Sortir:
2315970974512 JavaTpoint 1977728175088
Encore une fois, on modifie la valeur de x en ajoutant une nouvelle chaîne, et on obtient la nouvelle adresse mémoire. Essayons d'ajouter une chaîne directement dans s.
s = 'java' s[0] = T print(id(s))
Sortir:
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
Le code ci-dessus renvoie une erreur, cela signifie que la chaîne ne prend pas en charge la mutation. Donc str ce sont les objets immuables.
Maintenant, nous allons voir l'objet mutable tel que la liste.
c
my_list = [3, 4, 8] print(id(my_list)) my_list.append(4) print(my_list) print(id(my_list))
Sortir:
2571132658944 [3, 4, 8, 4] 2571132658944
Comme nous pouvons le voir dans le code ci-dessus, le ma liste a l'identifiant à l'origine, et nous avons ajouté 5 à la liste ; ma liste a le même identifiant car la liste prend en charge le mutabilité.
Comprendre les variables Python
La manière de définir les variables en Python est très différente de celle du C ou du C++. La variable Python ne définit pas le type de données. En fait, Python a des noms, pas des variables.
Nous devons donc comprendre la différence entre les variables et les noms, ce qui est particulièrement vrai lorsque nous abordons le sujet délicat des pointeurs en Python.
Comprenons comment fonctionne la variable en C et comment fonctionne le nom en Python.
Variables en C
En langage C, une variable est qu'elle contient une valeur ou stocke une valeur. Il est défini avec le type de données. Voyons le code suivant qui définit la variable.
int x = 286;
- Allouez suffisamment de mémoire pour un entier.
- Nous attribuons la valeur 286 à cet emplacement mémoire.
- Le x représente cette valeur.
Si nous représentons le point de vue de la mémoire -
Comme nous pouvons le voir, le x a un emplacement mémoire pour la valeur 286. Nous allons maintenant attribuer la nouvelle valeur à x.
x = 250
Cette nouvelle valeur écrase la valeur précédente. Cela signifie que la variable x est mutable.
L'emplacement de la valeur de x est le même, mais la valeur a changé. C'est un point important indiquant que x est l'emplacement mémoire, pas seulement son nom.
Maintenant, nous introduisons la nouvelle variable qui prend le x, puis le y crée la nouvelle boîte mémoire.
int y = x;
La variable y crée une nouvelle boîte appelée y copie la valeur de x dans la boîte.
Noms en Python
Comme nous en avons discuté précédemment, Python n'a pas les variables. Il a des noms, et nous utilisons ce terme comme variables. Mais il existe une différence entre les variables et les noms. Voyons l'exemple suivant.
x = 289
Le code ci-dessus est décomposé lors de l'exécution.
- Créer un PyObject
- Définissez le code de type sur entier pour le PyObject
- Définissez la valeur sur 289 pour le PyObject
- Créez un nom appelé x
- Pointez x vers le nouveau PyObject
- Augmentez le refcount du PyObject de 1
Cela ressemblera à ci-dessous.
Java a la suite
Nous pouvons comprendre le fonctionnement interne d'une variable en Python. La variable x pointe vers la référence de l'objet et elle n'a plus l'espace mémoire comme avant. Cela montre également que x = 289 lie le nom x à une référence.
Maintenant, nous introduisons une nouvelle variable et lui attribuons x.
y = x
En Python, la variable y ne créera pas le nouvel objet ; c'est juste un nouveau nom pointant vers le même objet. L'object refcount également augmenté d’un. Nous pouvons le confirmer comme suit.
y is x
Sortir:
True
Si on augmente la valeur de y de un, il ne fera plus référence au même objet.
y + =1 y is x
Cela signifie qu'en Python, nous n'attribuons pas de variables. Au lieu de cela, nous lions les noms à des références.
Simulation de pointeurs en Python
Comme nous l'avons discuté, Python ne prend pas en charge le pointeur, mais nous pouvons bénéficier des avantages de l'utilisation d'un pointeur. Python propose d'autres moyens d'utiliser le pointeur en Python. Ces deux manières sont indiquées ci-dessous.
- Utiliser des types mutables comme pointeurs
- Utiliser des objets Python personnalisés
Comprenons les points donnés.
Utiliser des types mutables comme pointeur
Dans la section précédente, nous avons défini les objets de type mutable ; nous pouvons les traiter comme s'il s'agissait de pointeurs pour simuler le comportement du pointeur. Comprenons l'exemple suivant.
C
void add_one(int *a) { *a += 1; }
Dans le code ci-dessus, nous avons défini le pointeur *a, puis nous incrémentons la valeur de un. Maintenant, nous allons l'implémenter avec la fonction main().
système d'exploitation Linux
#include int main(void) { int y = 233; printf('y = %d ', y); add_one(&y); printf('y = %d ', y); return 0; }
Sortir:
y = 233 y = 234
Nous pouvons simuler ce type de comportement en utilisant le type mutable Python. Comprenez l’exemple suivant.
def add_one(x): x[0] += 1 y = [2337] add_one(y) y[0]
La fonction ci-dessus accède au premier élément de la liste et incrémente sa valeur de un. Lorsque nous exécutons le programme ci-dessus, il imprime la valeur modifiée de y. Cela signifie que nous pouvons répliquer le pointeur en utilisant l'objet mutable. Mais si nous essayons de simuler un pointeur en utilisant un objet immuable.
z = (2337,) add_one(z)
Sortir:
Traceback (most recent call last): File '', line 1, in File '', line 2, in add_one TypeError: 'tuple' object does not support item assignment
Nous avons utilisé le tuple dans le code ci-dessus, un objet immuable, il a donc renvoyé l'erreur. On peut également utiliser le dictionnaire pour simuler le pointeur en Python.
Comprenons l'exemple suivant où nous compterons chaque opération qui se produit dans le programme. Nous pouvons utiliser dict pour y parvenir.
Exemple -
count = {'funcCalls': 0} def car(): count['funcCalls'] += 1 def foo(): count['funCcalls'] += 1 car() foo() count['funcCalls']
Sortir:
2
Explication -
Dans l'exemple ci-dessus, nous avons utilisé le compter dictionnaire, qui gardait une trace du nombre d’appels de fonction. Quand le foo() la fonction est appelée, le compteur est augmenté de 2 car dict est mutable.
Utiliser des objets Python
Dans l'exemple précédent, nous avons utilisé dict pour émuler le pointeur en Python, mais il devient parfois difficile de se souvenir de tous les noms de clés utilisés. Nous pouvons utiliser la classe personnalisée Python à la place du dictionnaire. Comprenons l'exemple suivant.
Exemple -
class Pointer(object): def __init__(self): self._metrics = { 'funCalls': 0, 'catPictures': 0, }
Dans le code ci-dessus, nous avons défini la classe Pointer. Cette classe utilisait dict pour conserver les données réelles dans la variable membre _metrics. Cela apportera de la mutabilité à notre programme. Nous pouvons procéder comme suit.
class Pointer(object): # ... @property def funCalls(self): return self._metrics['func_calls'] @property def catPictures_served(self): return self._metrics['cat_pictures_served']
Nous avons utilisé @propriété décorateur. Si vous n'êtes pas familier avec les décorateurs, visitez notre tutoriel sur les décorateurs Python. Le décorateur @property accédera à funCalls et catPicture_served. Maintenant, nous allons créer un objet de la classe Pointer.
pt = Pointer() pt.funCalls() pt.catPicture_served
Ici, nous devons incrémenter ces valeurs.
class Pointer(object): # ... def increament(self): self._metrices['funCalls'] += 1 def cat_pics(self): self._metrices['catPictures_served'] += 1
Nous avons défini deux nouvelles méthodes : incrément() et cat_pics(). Nous avons modifié les valeurs en utilisant ces fonctions dans le dict des matrices. Ici, nous pouvons changer la classe de la même manière que nous modifions le pointeur.
pt = Pointer() pt.increment() pt.increment() pt.funCalls()
Module ctypes Python
Le module Python ctypes nous permet de créer un pointeur de type C en Python. Ce module est utile si nous voulons effectuer un appel de fonction à une bibliothèque C nécessitant un pointeur. Comprenons l'exemple suivant.
Exemple - Langage C
void incr_one(int *x) { *x += 1; }
Dans la fonction ci-dessus, nous avons incrémenté la valeur de x de un. Supposons que nous enregistrions le fichier ci-dessus nommé incrPointer.c et la commande suivante dans le terminal.
$ gcc -c -Wall -Werror -fpic incrPointer.c $ gcc -shared -o libinc.so incrPointer.o
La première commande compile incrPointer.c dans un objet appelé incrPointer.o. La deuxième commande accepte le fichier objet et produit libinic.so pour collaborer avec les ctypes.
1 million de nombre
import ctypes ## libinc.so library should be same directory as this program lib = ctypes.CDLL('./libinc.so') lib.increment
Sortir:
Dans le code ci-dessus, le ctypes.CDLL renvoie un objet partagé appelé libinique.so. Il contient le incrPointeur() fonction. Si nous devons spécifier le pointeur vers les fonctions que nous définissons dans un objet partagé, nous devons le spécifier en utilisant les ctypes. Voyons l'exemple ci-dessous.
inc = lib.increment ## defining the argtypes inc.argtypes = [ctypes.POINTER(ctypes.c_int)]
Si nous appelons la fonction en utilisant un type différent, cela entraînera une erreur.
incrPointer(10)
Sortir:
Traceback (most recent call last): File '', line 1, in ctypes.ArgumentError: argument 1: : expected LP_c_int instance instead of int
En effet, incrPointer nécessite un pointeur et ctypes est un moyen de passer un pointeur en Python.
v = ctypes.c_int(10)
v est une variable C. Le ctypes fournit la méthode appelée par référence() qui passait la référence de la variable.
inc(ctypes.byref(a)) a
Sortir:
c_int(11)
Nous avons augmenté la valeur en utilisant la variable de référence.
Conclusion
Nous avons discuté du fait que le pointeur n'est pas présent dans Python, mais nous pouvons implémenter le même comportement avec l'objet *mutable. Nous avons également discuté des modules ctypes qui peuvent définir le pointeur C en Python. Nous avons défini quelques excellentes façons de simuler un pointeur en Python.