Ich weiß, dass Python keine Zeiger hat, aber gibt es eine Möglichkeit, 2
stattdessen diese Ausbeute zu erzielen ?
>>> a = 1
>>> b = a # modify this line somehow so that b "points to" a
>>> a = 2
>>> b
1
?
Hier ein Beispiel: Ich möchte form.data['field']
und form.field.value
soll immer den gleichen Wert haben. Es ist nicht unbedingt notwendig, aber ich denke, es wäre schön.
In PHP kann ich das zum Beispiel tun:
<?php
class Form {
public $data = [];
public $fields;
function __construct($fields) {
$this->fields = $fields;
foreach($this->fields as &$field) {
$this->data[$field['id']] = &$field['value'];
}
}
}
$f = new Form([
[
'id' => 'fname',
'value' => 'George'
],
[
'id' => 'lname',
'value' => 'Lucas'
]
]);
echo $f->data['fname'], $f->fields[0]['value']; # George George
$f->data['fname'] = 'Ralph';
echo $f->data['fname'], $f->fields[0]['value']; # Ralph Ralph
Ausgabe:
GeorgeGeorgeRalphRalph
Oder so in C ++ (ich denke das ist richtig, aber mein C ++ ist rostig):
#include <iostream>
using namespace std;
int main() {
int* a;
int* b = a;
*a = 1;
cout << *a << endl << *b << endl; # 1 1
return 0;
}
a, b = b, a
.Antworten:
Dies ist möglich, weil es ergänzte Namen und Indizierung beinhaltet - also völlig unterschiedliche Konstrukte aus der barenames
a
undb
dass Sie fragen über, und für Ihre Anfrage ist völlig unmöglich. Warum fragen Sie nach etwas unmöglich und völlig verschieden von dem (möglichen) , was Sie wirklich wollen ?Vielleicht merkt man nicht, wie drastisch unterschiedliche Barennamen und dekorierte Namen sind. Wenn Sie sich auf einen Barennamen beziehen
a
, erhalten Sie genau das Objekt, ana
das zuletzt in diesem Bereich gebunden wurde (oder eine Ausnahme, wenn es nicht in diesem Bereich gebunden war) - dies ist ein so tiefer und grundlegender Aspekt von Python, dass dies möglich ist möglicherweise nicht untergraben werden. Wenn Sie sich auf einen dekorierten Namen beziehen,x.y
bitten Sie ein Objekt (auf das sich das Objektx
bezieht), "dasy
Attribut" anzugeben - und als Antwort auf diese Anforderung kann das Objekt völlig willkürliche Berechnungen durchführen (und die Indizierung ist ziemlich ähnlich: es ermöglicht auch die Durchführung beliebiger Berechnungen als Antwort).Nun ist Ihr Beispiel für "tatsächliche Desiderata" mysteriös, da in jedem Fall zwei Ebenen der Indizierung oder Attributerfassung beteiligt sind, sodass die von Ihnen gewünschte Subtilität auf viele Arten eingeführt werden kann. Welche anderen Attribute
form.field
sollen zum Beispiel daneben habenvalue
? Ohne diese weiteren.value
Berechnungen würden Möglichkeiten umfassen:und
Das Vorhandensein von
.value
schlägt vor, die erste Form sowie eine Art nutzlosen Wrapper auszuwählen:Wenn Zuweisungen wie diese
form.field.value = 23
auch den Eintrag festlegen sollen,form.data
muss der Wrapper tatsächlich komplexer und nicht allzu nutzlos werden:Das letztere Beispiel kommt in Python dem Sinn eines "Zeigers" ungefähr so nahe, wie Sie es zu wollen scheinen - aber es ist wichtig zu verstehen, dass solche Feinheiten immer nur mit Indizierung und / oder dekorierten Namen funktionieren können , niemals mit barenamen wie du ursprünglich gefragt hast!
quelle
Es gibt keine Möglichkeit, nur diese Zeile zu ändern. Du kannst tun:
Das erstellt eine Liste, weist die Referenz a zu, dann verwendet b auch die Referenz a, um das erste Element auf 2 zu setzen, und greift dann mit der Referenzvariablen b zu.
quelle
a
undb
die Liste ist nicht der Wert in der Liste. Die Variablen ändern ihre Zuordnung nicht, das Objekt ist dasselbe Objekt. Wenn es sich ändert, wie im Fall der Änderung der Ganzzahl (von denen jedes ein anderes Objekt ist), wirda
es jetzt einem anderen Objekt zugewiesen, und es gibt keine Aufforderung, diesem Beispielb
zu folgen. Hiera
wird nicht neu zugewiesen, sondern ein Wert innerhalb des Objekts, dem es zugewiesen ist, ändert sich. Dab
es immer noch an dieses Objekt gebunden ist, werden dieses Objekt und die Änderungen an den darin enthaltenen Werten wiedergegeben.Es ist kein Fehler, es ist ein Feature :-)
Wenn Sie sich den Operator '=' in Python ansehen, denken Sie nicht an die Zuweisung. Sie weisen keine Dinge zu, Sie binden sie. = ist ein Bindungsoperator.
In Ihrem Code geben Sie dem Wert 1 einen Namen: a. Dann geben Sie dem Wert in 'a' einen Namen: b. Dann binden Sie den Wert 2 an den Namen 'a'. Der an b gebundene Wert ändert sich bei dieser Operation nicht.
Aus C-ähnlichen Sprachen kommend, kann dies verwirrend sein, aber sobald Sie sich daran gewöhnt haben, werden Sie feststellen, dass es Ihnen hilft, Ihren Code klarer zu lesen und zu begründen: Der Wert mit dem Namen 'b' ändert sich nur, wenn Sie explizit ändern. Und wenn Sie dies importieren, werden Sie feststellen, dass das Zen von Python besagt, dass Explizit besser als implizit ist.
Beachten Sie auch, dass funktionale Sprachen wie Haskell dieses Paradigma ebenfalls verwenden, was hinsichtlich der Robustheit von großem Wert ist.
quelle
a = 1; b = a; a = 2;
ist in Python, C und Java genau das gleiche: b ist 1. Warum ist dieser Fokus auf "= ist keine Zuweisung, es ist bindend"?a
undb
während in Python, sie beide beziehen sich auf die gleichen „1“ (glaube ich). Wenn Sie also den Wert 1 ändern könnten (wie bei Objekten), wäre dies anders. Was zu einigen seltsamen Box- / Unboxing-Problemen führt, höre ich.Ja! Es gibt eine Möglichkeit, eine Variable als Zeiger in Python zu verwenden!
Es tut mir leid zu sagen, dass viele Antworten teilweise falsch waren. Im Prinzip teilt sich jede gleiche (=) Zuweisung die Speicheradresse (überprüfen Sie die ID (obj) -Funktion), in der Praxis ist dies jedoch nicht der Fall. Es gibt Variablen, deren gleiches ("=") Verhalten im letzten Term als Kopie des Speicherplatzes fungiert, hauptsächlich in einfachen Objekten (z. B. "int" -Objekt) und in anderen, in denen dies nicht der Fall ist (z. B. "list" -, "dict" -Objekte). .
Hier ist ein Beispiel für die Zeigerzuweisung
Hier ist ein Beispiel für die Zuweisung von Kopien
Die Zeigerzuweisung ist ein ziemlich nützliches Werkzeug für das Aliasing ohne Verschwendung von zusätzlichem Speicher, in bestimmten Situationen für die Ausführung von komfortablem Code.
Man muss sich dieser Verwendung jedoch bewusst sein, um Codefehler zu vermeiden.
Abschließend sind einige Variablen standardmäßig Barennamen (einfache Objekte wie int, float, str, ...) und einige Zeiger, wenn sie zwischen ihnen zugewiesen werden (z. B. dict1 = dict2). Wie erkennt man sie? Probieren Sie einfach dieses Experiment mit ihnen. In IDEs mit variablem Explorer scheint das Bedienfeld normalerweise die Speicheradresse ("@axbbbbbb ...") in der Definition von Zeigermechanismusobjekten zu sein.
Ich schlage vor, im Thema zu untersuchen. Es gibt viele Leute, die sicher viel mehr über dieses Thema wissen. (siehe Modul "ctypes"). Ich hoffe es ist hilfreich. Genießen Sie die gute Nutzung der Objekte! Grüße, José Crespo
quelle
Wie Sie sehen können
a
undb
nur zwei verschiedene Namen sind, die auf dasselbe unveränderliche Objekt (int) verweisen1
. Wenn Sie später schreibena = 2
, weisen Sie den Namena
einem anderen Objekt (int) zu2
, aber dasb
verweist weiterhin auf1
:Was würde passieren, wenn Sie stattdessen ein veränderbares Objekt wie eine Liste hätten
[1]
?Wiederum verweisen wir auf dasselbe Objekt (Liste)
[1]
mit zwei verschiedenen Namena
undb
. Aber jetzt können wir diese Liste mutieren , während sie das gleiche Objekt bleibt, unda
,b
werden beide weiterhin darauf verweisenquelle
Aus einer Sicht ist in Python alles ein Zeiger. Ihr Beispiel funktioniert sehr ähnlich wie der C ++ - Code.
(Ein näheres Äquivalent würde eine Art von
shared_ptr<Object>
anstelle von verwendenint*
.)Sie können dies tun, indem Sie
__getitem__
inform.data
der Klasse überladen .quelle
form.data
ist keine Klasse. Ist es notwendig, es zu einem zu machen, oder kann ich es im laufenden Betrieb überschreiben? (Es ist nur ein Python-Diktat) Außerdem müssten Daten einen Verweis auf haben,form
um auf die Felder zugreifen zu können ... was die Implementierung dieses hässlich macht.Dies ist ein Python-Zeiger (anders als c / c ++)
quelle
Ich habe die folgende einfache Klasse geschrieben, um einen Zeiger in Python effektiv zu emulieren:
Hier ist ein Anwendungsbeispiel (von einer Jupyter-Notizbuchseite):
Natürlich ist es auch einfach, diese Funktion für diktierte Elemente oder Attribute eines Objekts zu verwenden. Es gibt sogar eine Möglichkeit, mit globals () das zu tun, wonach das OP gefragt hat:
Dies druckt 2 aus, gefolgt von 3.
Auf diese Weise mit dem globalen Namespace zu spielen, ist eine schreckliche Idee, aber es zeigt, dass es möglich ist (wenn nicht ratsam), das zu tun, was das OP verlangt.
Das Beispiel ist natürlich ziemlich sinnlos. Ich habe jedoch festgestellt, dass diese Klasse in der Anwendung, für die ich sie entwickelt habe, nützlich ist: ein mathematisches Modell, dessen Verhalten von zahlreichen vom Benutzer einstellbaren mathematischen Parametern verschiedener Typen bestimmt wird (die, da sie von Befehlszeilenargumenten abhängen, nicht bekannt sind zur Kompilierungszeit). Und sobald der Zugriff auf etwas in einem Parameter-Objekt gekapselt wurde, können alle diese Objekte auf einheitliche Weise bearbeitet werden.
Obwohl es nicht viel wie ein C- oder C ++ - Zeiger aussieht, löst dies ein Problem, das ich mit Zeigern gelöst hätte, wenn ich in C ++ geschrieben hätte.
quelle
Der folgende Code emuliert genau das Verhalten von Zeigern in C:
Hier sind Anwendungsbeispiele:
Jetzt ist es an der Zeit, einen professionelleren Code anzugeben, einschließlich der Option zum Löschen von Zeigern, die ich gerade in meiner persönlichen Bibliothek gefunden habe:
quelle