logo

Puntatore in Python | Perché Python non supporta il puntatore

In questo tutorial impareremo a conoscere il puntatore in Python e vedremo perché Python non supporta i concetti di puntatore.

Capiremo anche come simulare il puntatore in Python. Di seguito è riportata l'introduzione del puntatore per coloro che non ne hanno.

Capiremo anche come simulare il puntatore in Python. Di seguito è riportata l'introduzione del puntatore per coloro che non ne hanno.

Cos'è il puntatore?

Il puntatore è uno strumento molto popolare e utile per memorizzare l'indirizzo della variabile. Se qualcuno ha mai lavorato con un linguaggio di basso livello come C . C++ , probabilmente avrà familiarità con i puntatori. Gestisce il codice in modo molto efficiente. Può essere leggermente difficile per i principianti, ma è uno dei concetti importanti del programma. Tuttavia, può portare a vari bug nella gestione della memoria. Pertanto, la definizione di puntatori -

'I puntatori sono le variabili che contengono l'indirizzo di memoria di un'altra variabile. Le variabili puntatore sono rappresentate da un asterisco (*).'

Vediamo il seguente esempio del puntatore nel linguaggio di programmazione C.

Esempio: come utilizzare il puntatore in 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; } 

Produzione:

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 

Oltre ad essere utili, i puntatori non vengono utilizzati in Pitone . In questo argomento discuteremo del modello a oggetti di Python e scopriremo perché i puntatori in Python non esistono. Impareremo anche diversi modi per simulare i puntatori in Python. Per prima cosa, discutiamo perché Python non supporta i puntatori.

Perché Python non supporta i puntatori

La ragione esatta per non supportare il puntatore non è chiara. Il puntatore in Python potrebbe esistere in modo nativo? Il concetto principale di Python è la sua semplicità, ma il puntatore ha violato il concetto Zen di Pitone. I puntatori sono principalmente incoraggiati a cambiamenti impliciti piuttosto che a quelli espliciti. Sono anche complessi, soprattutto per i principianti.

I puntatori tendono a creare complessità nel codice, mentre Python si concentra principalmente sull'usabilità piuttosto che sulla velocità. Di conseguenza, Python non supporta il puntatore. Tuttavia, Python offre alcuni vantaggi nell'uso del puntatore.

Prima di comprendere il puntatore in Python, dobbiamo avere l'idea di base dei seguenti punti.

  • Oggetti immutabili e oggetti mutabili
  • Variabili/nomi Python

Oggetti in Python

In Python, tutto è un oggetto, anche classi, funzioni, variabili, ecc. Ogni oggetto contiene almeno tre dati.

istanza Java di
  • Conteggio dei riferimenti
  • Tipo
  • Valore

Discutiamo uno per uno.

Conteggio riferimenti - Viene utilizzato per la gestione della memoria. Per ottenere maggiori informazioni sulla gestione della memoria Python, leggi Gestione della memoria in Python.

Tipo - IL CPython il layer viene utilizzato come tipo per garantire l'indipendenza dal tipo durante il runtime. Infine, c'è un valore, che è il valore effettivo associato all'oggetto.

Se andiamo in profondità in questo oggetto, scopriremo che non tutti gli oggetti sono uguali. L'importante distinzione tra i tipi di oggetto è immutabile e mutevole. Prima di tutto dobbiamo capire la differenza tra i tipi di oggetto perché esplora il puntatore in Python.

Oggetti immutabili e oggetti mutabili

Gli oggetti immutabili non possono essere modificati, mentre gli oggetti mutabili possono essere modificati. Vediamo la seguente tabella dei tipi comuni e se sono mutabili o meno.

Oggetti Tipo
interno Immutabile
Galleggiante Immutabile
Bool Immutabile
Elenco Mutevole
Impostato Mutevole
Complesso Mutevole
Tupla Immutabile
Frozenset Immutabile
Dict Mutevole

Possiamo verificare il tipo degli oggetti di cui sopra utilizzando il file id() metodo. Questo metodo restituisce l'indirizzo di memoria dell'oggetto.

alberi divaricati

Stiamo digitando le righe seguenti in un ambiente REPL.

 x = 5 id(x) 

Produzione:

140720979625920 

Nel codice precedente abbiamo assegnato il valore 10 a x. se modificassimo questo valore con la sostituzione, otterremmo i nuovi oggetti.

 x-=1 id(x) 

Produzione:

140720979625888 

Come possiamo vedere, modifichiamo il codice sopra e otteniamo nuovi oggetti come risposta. Facciamo un altro esempio di stra .

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

Produzione:

2315970974512 JavaTpoint 1977728175088 

Ancora una volta modifichiamo il valore di x aggiungendo una nuova stringa e otteniamo il nuovo indirizzo di memoria. Proviamo ad aggiungere la stringa direttamente in s.

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

Produzione:

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 

Il codice sopra restituisce un errore, significa che la stringa non supporta la mutazione. COSÌ stra sono gli oggetti immutabili.

Ora vedremo l'oggetto mutabile come list.

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

Produzione:

2571132658944 [3, 4, 8, 4] 2571132658944 

Come possiamo vedere nel codice sopra, il file la mia lista ha l'id originale e abbiamo aggiunto 5 all'elenco; la mia lista ha lo stesso ID perché l'elenco supporta il file mutabilità.

Comprendere le variabili Python

Il modo di definire le variabili in Python è molto diverso da C o C++. La variabile Python non definisce il tipo di dati. In effetti, Python ha nomi, non variabili.

Quindi dobbiamo comprendere la differenza tra variabili e nomi, cosa particolarmente vera quando esploriamo il complicato argomento dei puntatori in Python.

Capiamo come funziona la variabile in C e come funziona il nome in Python.

Variabili in C

Nel linguaggio C, una variabile è che contiene valore o memorizza valore. È definito con il tipo di dati. Vediamo il seguente codice che definisce la variabile.

 int x = 286; 
  • Allocare memoria sufficiente per un numero intero.
  • Assegniamo il valore 286 a quella posizione di memoria.
  • La x rappresenta quel valore.

Se rappresentiamo la visione della memoria -

Puntatore in Python

Come possiamo vedere, x ha una posizione di memoria per il valore 286. Ora assegneremo il nuovo valore a x.

x = 250

Questo nuovo valore sovrascrive il valore precedente. Significa che la variabile x è mutevole.

stringa in C++

La posizione del valore di x è la stessa, ma il valore è cambiato. È un punto significativo che indica che x è la posizione di memoria, non solo il suo nome.

Ora introduciamo la nuova variabile che prende la x, quindi la y crea la nuova casella di memoria.

 int y = x; 

La variabile y crea una nuova scatola chiamata y copia il valore di x nella scatola.

Puntatore in Python

Nomi in Python

Come abbiamo discusso in precedenza, Python non ha variabili. Ha nomi e usiamo questo termine come variabili. Ma c'è una differenza tra variabili e nomi. Vediamo il seguente esempio.

 x = 289 

Il codice precedente viene scomposto durante l'esecuzione.

  1. Crea un PyObject
  2. Imposta il typecode su intero per PyObject
  3. Imposta il valore su 289 per PyObject
  4. Crea un nome chiamato x
  5. Punta x al nuovo PyObject
  6. Aumenta il conteggio di PyObject di 1

Apparirà come sotto.

Puntatore in Python

Possiamo comprendere il funzionamento interno di una variabile in Python. La variabile x punta al riferimento dell'oggetto e non ha lo spazio di memoria come prima. Mostra anche che x = 289 lega il nome x a un riferimento.

Ora introduciamo una nuova variabile e le assegniamo x.

 y = x 

In Python, la variabile y non creerà il nuovo oggetto; è semplicemente un nuovo nome che punta allo stesso oggetto. L'oggetto refcount anch'esso aumentato di uno. Possiamo confermarlo come segue.

 y is x 

Produzione:

True 

Se aumentiamo il valore di y di uno, non si riferirà più allo stesso oggetto.

 y + =1 y is x 

Ciò significa che in Python non assegniamo variabili. Invece, leghiamo i nomi al riferimento.

Simulazione di puntatori in Python

Come abbiamo discusso, Python non supporta i puntatori, ma possiamo ottenere i vantaggi dell'utilizzo di un puntatore. Python fornisce modi alternativi per utilizzare il puntatore in Python. Questi due modi sono indicati di seguito.

  • Utilizzo di tipi mutabili come puntatori
  • Utilizzo di oggetti Python personalizzati

Comprendiamo i punti dati.

Utilizzo di tipi mutabili come puntatore

Nella sezione precedente abbiamo definito gli oggetti di tipo mutabile; possiamo trattarli come se fossero puntatori per simulare il comportamento dei puntatori. Comprendiamo il seguente esempio.

C

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

Nel codice sopra, abbiamo definito il puntatore *a, quindi incrementiamo il valore di uno. Ora lo implementeremo con la funzione main().

corda in c
 #include int main(void) { int y = 233; printf('y = %d
', y); add_one(&y); printf('y = %d
', y); return 0; } 

Produzione:

y = 233 y = 234 

Possiamo simulare questo tipo di comportamento utilizzando il tipo mutabile Python. Comprendi il seguente esempio.

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

La funzione precedente accede al primo elemento dell'elenco e ne incrementa il valore di uno. Quando eseguiamo il programma sopra, stampa il valore modificato di y. Significa che possiamo replicare il puntatore utilizzando l'oggetto mutabile. Ma se proviamo a simulare il puntatore utilizzando un oggetto immutabile.

 z = (2337,) add_one(z) 

Produzione:

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

Abbiamo usato la tupla nel codice sopra, un oggetto immutabile, quindi ha restituito l'errore. Possiamo anche usare il dizionario per simulare il puntatore in Python.

Comprendiamo l'esempio seguente in cui conteremo ogni operazione che si verifica nel programma. Possiamo usare dict per raggiungere questo obiettivo.

Esempio -

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

Produzione:

2 

Spiegazione -

Nell'esempio sopra abbiamo utilizzato il file contare dizionario, che teneva traccia del numero di chiamate di funzione. Quando il pippo() viene chiamata la funzione, il contatore viene aumentato di 2 perché dict è mutabile.

Utilizzo di oggetti Python

Nell'esempio precedente abbiamo utilizzato dict per emulare il puntatore in Python, ma a volte diventa difficile ricordare tutti i nomi delle chiavi utilizzate. Possiamo usare la classe personalizzata Python al posto del dizionario. Comprendiamo il seguente esempio.

Esempio -

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

Nel codice precedente, abbiamo definito la classe Pointer. Questa classe utilizzava dict per conservare i dati effettivi nella variabile membro _metrics. Fornirà mutabilità al nostro programma. Possiamo farlo come segue.

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

Abbiamo usato @proprietà decoratore. Se non hai familiarità con i decoratori, visita il nostro tutorial sul decoratore Python. Il decoratore @property accederà a funCalls e catPicture_served. Ora creeremo un oggetto della classe Pointer.

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

Qui dobbiamo incrementare questi valori.

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

Abbiamo definito due nuovi metodi: incrementa() e cat_pics(). Abbiamo modificato i valori utilizzando queste funzioni nelle matrici dict. Qui possiamo cambiare la classe nello stesso modo in cui stiamo modificando il puntatore.

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

Modulo ctypes Python

Il modulo Python ctypes ci consente di creare un puntatore di tipo C in Python. Questo modulo è utile se vogliamo effettuare una chiamata di funzione a una libreria C che richiede un puntatore. Comprendiamo il seguente esempio.

Esempio: linguaggio C

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

Nella funzione precedente, abbiamo incrementato il valore di x di uno. Supponiamo di salvare il file sopra denominato incrPointer.c e di digitare il seguente comando nel terminale.

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

Il primo comando viene compilato incrPointer.c in un oggetto chiamato incrPointer.o. Il secondo comando accetta il file oggetto e produce libinic.so per collaborare con ctypes.

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

Produzione:

 

Nel codice precedente, il ctypes.CDLL restituisce un oggetto condiviso chiamato libinico.so. Contiene il incrPointer() funzione. Se dobbiamo specificare il puntatore alle funzioni che definiamo in un oggetto condiviso, dobbiamo specificarlo utilizzando i ctypes. Vediamo l'esempio qui sotto.

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

Se chiamiamo la funzione utilizzando un tipo diverso, si verificherà un errore.

 incrPointer(10) 

Produzione:

Traceback (most recent call last): File '', line 1, in ctypes.ArgumentError: argument 1: : expected LP_c_int instance instead of int 

Questo perché incrPointer richiede un puntatore e ctypes è un modo per passare il puntatore in Python.

 v = ctypes.c_int(10) 

v è una variabile C. I ctypes forniscono il metodo chiamato perref() che veniva utilizzato per passare il riferimento alla variabile.

 inc(ctypes.byref(a)) a 

Produzione:

c_int(11) 

Abbiamo aumentato il valore utilizzando la variabile di riferimento.

Conclusione

Abbiamo discusso del fatto che il puntatore non è presente in Python, ma possiamo implementare lo stesso comportamento con l'oggetto *mutable. Abbiamo anche discusso i moduli ctypes che possono definire il puntatore C in Python. Abbiamo definito alcuni modi eccellenti per simulare il puntatore in Python.