logo

Zeiger in Python | Warum Python Zeiger nicht unterstützt

In diesem Tutorial lernen wir etwas über Zeiger in Python und erfahren, warum Python Zeigerkonzepte nicht unterstützt.

Wir werden auch verstehen, wie wir den Zeiger in Python simulieren können. Nachfolgend finden Sie die Einführung des Zeigers für diejenigen, die noch keine Ahnung davon haben.

Wir werden auch verstehen, wie wir den Zeiger in Python simulieren können. Nachfolgend finden Sie eine Einführung in den Zeiger für diejenigen, die noch keine Ahnung davon haben.

Was ist Zeiger?

Zeiger ist ein sehr beliebtes und nützliches Werkzeug zum Speichern der Adresse der Variablen. Wenn jemand jemals mit einer Low-Level-Sprache gearbeitet hat, wie z C . C++ , er/sie wäre wahrscheinlich mit Hinweisen vertraut. Es verwaltet den Code sehr effizient. Für Anfänger kann es etwas schwierig sein, aber es ist eines der wichtigen Konzepte des Programms. Es kann jedoch zu verschiedenen Fehlern bei der Speicherverwaltung führen. Somit ist die Definition von Zeigern -

'Zeiger sind die Variablen, die die Speicheradresse einer anderen Variablen enthalten. Zeigervariablen werden durch ein Sternchen (*) dargestellt.'

Sehen wir uns das folgende Beispiel des Zeigers in der Programmiersprache C an.

Beispiel – Verwendung eines Zeigers 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; } 

Ausgabe:

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 

Zeiger sind nicht nur nützlich, sondern werden auch nicht verwendet Python . In diesem Thema besprechen wir das Objektmodell von Python und erfahren, warum es in Python keine Zeiger gibt. Wir lernen auch verschiedene Möglichkeiten kennen, Zeiger in Python zu simulieren. Lassen Sie uns zunächst diskutieren, warum Python Zeiger nicht unterstützt.

Warum unterstützt Python keine Zeiger?

Der genaue Grund für die Nichtunterstützung des Zeigers ist nicht klar. Könnte ein Zeiger in Python nativ existieren? Das Hauptkonzept von Python ist seine Einfachheit, aber der Zeiger verletzt dies Zen von Python. Bei Zeigern handelt es sich hauptsächlich um implizite und nicht um explizite Änderungen. Sie sind auch komplex, insbesondere für Anfänger.

Zeiger neigen dazu, Komplexität im Code zu erzeugen, während Python sich hauptsächlich auf Benutzerfreundlichkeit und nicht auf Geschwindigkeit konzentriert. Aus diesem Grund unterstützt Python keine Zeiger. Allerdings bietet Python einige Vorteile bei der Verwendung des Zeigers.

Bevor wir den Zeiger in Python verstehen, müssen wir die Grundidee der folgenden Punkte kennen.

  • Unveränderliche vs. veränderliche Objekte
  • Python-Variablen/Namen

Objekte in Python

In Python ist alles ein Objekt, sogar Klassen, Funktionen, Variablen usw. Jedes Objekt enthält mindestens drei Datenelemente.

Java-Instanz von
  • Referenzanzahl
  • Typ
  • Wert

Lassen Sie uns einzeln besprechen.

Referenzanzahl - Es dient der Speicherverwaltung. Weitere Informationen zur Python-Speicherverwaltung finden Sie unter Speicherverwaltung in Python.

Typ - Der CPython Die Schicht wird als Typ verwendet, um die Typsicherheit während der Laufzeit sicherzustellen. Schließlich gibt es einen Wert, der der tatsächliche Wert ist, der dem Objekt zugeordnet ist.

Wenn wir uns näher mit diesem Objekt befassen, werden wir jedoch feststellen, dass nicht alle Objekte gleich sind. Der wichtige Unterschied zwischen den Objekttypen ist unveränderlich und veränderlich. Zunächst müssen wir den Unterschied zwischen den Objekttypen verstehen, da er den Zeiger in Python untersucht.

Unveränderliche vs. veränderliche Objekte

Unveränderliche Objekte können nicht geändert werden, während veränderliche Objekte geändert werden können. Sehen wir uns die folgende Tabelle gängiger Typen an und ob sie veränderbar sind oder nicht.

Objekte Typ
Int Unveränderlich
Schweben Unveränderlich
Bool Unveränderlich
Aufführen Veränderlich
Satz Veränderlich
Komplex Veränderlich
Tupel Unveränderlich
Frozenset Unveränderlich
Diktat Veränderlich

Wir können den Typ der oben genannten Objekte mithilfe von überprüfen Ausweis() Methode. Diese Methode gibt die Speicheradresse des Objekts zurück.

Wir geben die folgenden Zeilen in einer REPL-Umgebung ein.

 x = 5 id(x) 

Ausgabe:

140720979625920 

Im obigen Code haben wir x den Wert 10 zugewiesen. Wenn wir diesen Wert durch Substitution ändern würden, würden wir die neuen Objekte erhalten.

 x-=1 id(x) 

Ausgabe:

140720979625888 

Wie wir sehen können, ändern wir den obigen Code und erhalten als Antwort neue Objekte. Nehmen wir ein weiteres Beispiel str .

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

Ausgabe:

2315970974512 JavaTpoint 1977728175088 

Auch hier ändern wir den Wert von x, indem wir eine neue Zeichenfolge hinzufügen, und erhalten die neue Speicheradresse. Versuchen wir, einen String direkt in s hinzuzufügen.

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

Ausgabe:

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 

Der obige Code gibt einen Fehler zurück. Dies bedeutet, dass die Zeichenfolge die Mutation nicht unterstützt. Also str sind die unveränderlichen Objekte.

Jetzt sehen wir das veränderliche Objekt wie z. B. die Liste.

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

Ausgabe:

2571132658944 [3, 4, 8, 4] 2571132658944 

Wie wir im obigen Code sehen können, ist die meine Liste hat ursprünglich die ID und wir haben 5 an die Liste angehängt; meine Liste hat die gleiche ID, da die Liste die unterstützt Wandlungsfähigkeit.

Python-Variablen verstehen

Die Art und Weise, Variablen in Python zu definieren, unterscheidet sich stark von der in C oder C++. Die Python-Variable definiert den Datentyp nicht. Tatsächlich hat Python Namen, keine Variablen.

Daher müssen wir den Unterschied zwischen Variablen und Namen verstehen, insbesondere wenn wir uns mit dem kniffligen Thema der Zeiger in Python befassen.

Lassen Sie uns verstehen, wie die Variable in C und der Name in Python funktioniert.

Java-Binärbaum

Variablen in C

In der C-Sprache bedeutet eine Variable, dass sie einen Wert enthält oder einen Wert speichert. Es wird mit dem Datentyp definiert. Sehen wir uns den folgenden Code an, der die Variable definiert.

1 bis 100 römische Nr
 int x = 286; 
  • Weisen Sie ausreichend Speicher für eine Ganzzahl zu.
  • Wir weisen diesem Speicherort den Wert 286 zu.
  • Das x repräsentiert diesen Wert.

Wenn wir die Sicht der Erinnerung vertreten –

Zeiger in Python

Wie wir sehen können, hat das x einen Speicherort für den Wert 286. Nun weisen wir x den neuen Wert zu.

x = 250

Dieser neue Wert überschreibt den vorherigen Wert. Das bedeutet, dass die Variable x veränderlich ist.

Der Wertort von x ist derselbe, aber der Wert hat sich geändert. Dies ist ein wichtiger Punkt, der darauf hinweist, dass x der Speicherort und nicht nur sein Name ist.

Jetzt führen wir die neue Variable ein, die das x annimmt, und dann erstellt das y die neue Speicherbox.

 int y = x; 

Die Variable y erstellt ein neues Feld namens y und kopiert den Wert von x in das Feld.

Zeiger in Python

Namen in Python

Wie wir bereits besprochen haben, verfügt Python nicht über diese Variablen. Es hat Namen und wir verwenden diesen Begriff als Variablen. Es gibt jedoch einen Unterschied zwischen Variablen und Namen. Sehen wir uns das folgende Beispiel an.

 x = 289 

Der obige Code wird während der Ausführung zerlegt.

  1. Erstellen Sie ein PyObject
  2. Setzen Sie den Typcode für das PyObject auf Ganzzahl
  3. Legen Sie den Wert für das PyObject auf 289 fest
  4. Erstellen Sie einen Namen mit dem Namen x
  5. Zeigen Sie x auf das neue PyObject
  6. Erhöhen Sie den Refcount des PyObject um 1

Es wird wie folgt aussehen.

Zeiger in Python

Wir können die interne Funktionsweise einer Variablen in Python verstehen. Die Variable x zeigt auf die Referenz des Objekts und verfügt nicht über den gleichen Speicherplatz wie zuvor. Es zeigt auch, dass x = 289 den Namen x an eine Referenz bindet.

Jetzt führen wir eine neue Variable ein und weisen ihr x zu.

 y = x 

In Python erstellt die Variable y kein neues Objekt. Es handelt sich lediglich um einen neuen Namen, der auf dasselbe Objekt verweist. Das Objekt refcount ebenfalls um eins erhöht. Wir können es wie folgt bestätigen.

 y is x 

Ausgabe:

True 

Wenn wir den Wert von y um eins erhöhen, verweist es nicht mehr auf dasselbe Objekt.

 y + =1 y is x 

Das bedeutet, dass wir in Python keine Variablen zuweisen. Stattdessen binden wir Namen an Referenzen.

Zeiger in Python simulieren

Wie wir besprochen haben, unterstützt Python keine Zeiger, aber wir können die Vorteile der Verwendung eines Zeigers nutzen. Python bietet alternative Möglichkeiten zur Verwendung des Zeigers in Python. Diese beiden Möglichkeiten sind unten aufgeführt.

  • Veränderbare Typen als Zeiger verwenden
  • Verwendung benutzerdefinierter Python-Objekte

Lassen Sie uns die angegebenen Punkte verstehen.

Veränderbare Typen als Zeiger verwenden

Im vorherigen Abschnitt haben wir die Objekte vom veränderlichen Typ definiert; Wir können sie so behandeln, als wären sie Zeiger, um Zeigerverhalten zu simulieren. Lassen Sie uns das folgende Beispiel verstehen.

C

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

Im obigen Code haben wir den Zeiger *a definiert und dann den Wert um eins erhöht. Jetzt implementieren wir es mit der Funktion main().

Java-Beispielcode
 #include int main(void) { int y = 233; printf('y = %d
', y); add_one(&y); printf('y = %d
', y); return 0; } 

Ausgabe:

y = 233 y = 234 

Wir können diese Art von Verhalten simulieren, indem wir den veränderlichen Python-Typ verwenden. Verstehen Sie das folgende Beispiel.

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

Die obige Funktion greift auf das erste Element der Liste zu und erhöht seinen Wert um eins. Wenn wir das obige Programm ausführen, gibt es den geänderten Wert von y aus. Das bedeutet, dass wir den Zeiger mithilfe des veränderlichen Objekts replizieren können. Aber wenn wir versuchen, einen Zeiger mithilfe eines unveränderlichen Objekts zu simulieren.

 z = (2337,) add_one(z) 

Ausgabe:

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

Wir haben das Tupel im obigen Code verwendet, ein unveränderliches Objekt, daher wurde der Fehler zurückgegeben. Wir können das Wörterbuch auch verwenden, um den Zeiger in Python zu simulieren.

Lassen Sie uns das folgende Beispiel verstehen, in dem wir jeden Vorgang zählen, der im Programm ausgeführt wird. Wir können dict verwenden, um dies zu erreichen.

Beispiel -

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

Ausgabe:

2 

Erläuterung -

Im obigen Beispiel haben wir das verwendet zählen Wörterbuch, das die Anzahl der Funktionsaufrufe protokollierte. Wenn das foo() Wenn die Funktion aufgerufen wird, wird der Zähler um 2 erhöht, da das Diktat veränderbar ist.

Verwenden von Python-Objekten

Im vorherigen Beispiel haben wir dict verwendet, um den Zeiger in Python zu emulieren, aber manchmal wird es schwierig, sich alle verwendeten Schlüsselnamen zu merken. Wir können die benutzerdefinierte Python-Klasse anstelle des Wörterbuchs verwenden. Lassen Sie uns das folgende Beispiel verstehen.

Beispiel -

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

Im obigen Code haben wir die Pointer-Klasse definiert. Diese Klasse verwendete dict zum Speichern tatsächlicher Daten in der Mitgliedsvariablen _metrics. Es wird unserem Programm Veränderlichkeit verleihen. Wir können dies wie folgt tun.

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

Wir haben benutzt @Eigentum Dekorateur. Wenn Sie mit Dekoratoren nicht vertraut sind, besuchen Sie unser Python-Dekorator-Tutorial. Der @property-Dekorator greift auf funCalls und catPicture_served zu. Jetzt erstellen wir ein Objekt der Pointer-Klasse.

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

Hier müssen wir diese Werte erhöhen.

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

Wir haben zwei neue Methoden definiert – increment() und cat_pics(). Wir haben die Werte mithilfe dieser Funktionen im Matrizen-Dikt geändert. Hier können wir die Klasse auf die gleiche Weise ändern, wie wir den Zeiger ändern.

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

Python-ctypes-Modul

Mit dem Python-ctypes-Modul können wir einen C-Typ-Zeiger in Python erstellen. Dieses Modul ist hilfreich, wenn wir einen Funktionsaufruf an eine C-Bibliothek durchführen möchten, der einen Zeiger erfordert. Lassen Sie uns das folgende Beispiel verstehen.

Beispiel – C-Sprache

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

In der obigen Funktion haben wir den Wert von x um eins erhöht. Angenommen, wir speichern die obige Datei mit dem Namen incrPointer.c und geben den folgenden Befehl im Terminal ein.

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

Der erste Befehl kompiliert incrPointer.c in ein Objekt namens incrPointer.o. Der zweite Befehl akzeptiert die Objektdatei und erstellt libinic.so für die Zusammenarbeit mit ctypes.

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

Ausgabe:

 

Im obigen Code ist die ctypes.CDLL gibt ein gemeinsames Objekt mit dem Namen zurück libinic.so. Es enthält die incrPointer() Funktion. Wenn wir den Zeiger auf die Funktionen angeben müssen, die wir in einem gemeinsam genutzten Objekt definieren, müssen wir ihn mithilfe der ctypes angeben. Sehen wir uns das folgende Beispiel an.

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

Wenn wir die Funktion mit einem anderen Typ aufrufen, tritt ein Fehler auf.

 incrPointer(10) 

Ausgabe:

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

Dies liegt daran, dass incrPointer einen Zeiger erfordert und ctypes eine Möglichkeit ist, Zeiger in Python zu übergeben.

 v = ctypes.c_int(10) 

v ist eine C-Variable. Die ctypes stellen die aufgerufene Methode bereit byref() die verwendet wurde, um die Variablenreferenz zu übergeben.

 inc(ctypes.byref(a)) a 

Ausgabe:

c_int(11) 

Wir haben den Wert über die Referenzvariable erhöht.

Abschluss

Wir haben besprochen, dass der Zeiger in Python nicht vorhanden ist, aber wir können dasselbe Verhalten mit dem *mutable-Objekt implementieren. Wir haben auch die ctypes-Module besprochen, die C-Zeiger in Python definieren können. Wir haben einige hervorragende Möglichkeiten zur Simulation von Zeigern in Python definiert.