Hilfe mit copy und decopy in Python

9

Ich glaube, ich habe in meine vorherige Frage entschuldigt mich dafür. Lassen Sie mich meine Situation so einfach wie möglich darlegen.

Grundsätzlich habe ich eine Reihe von Wörterbüchern, die auf meine Objekte verweisen, die wiederum mit SQLAlchemy abgebildet werden. Alles in Ordnung mit mir. Ich möchte jedoch den Inhalt dieser Wörterbücher iterativ ändern. Das Problem besteht darin, dass dadurch die Objekte, auf die sie verweisen, geändert werden - und die Verwendung von copy.copy () ist nicht sinnvoll, da nur die im Wörterbuch enthaltenen Referenzen kopiert werden. Also selbst wenn ich etwas kopiere, wenn ich versuche, print den Inhalt des Wörterbuchs zu sagen, bekomme ich nur die neuesten aktualisierten Werte für das Objekt.

Deshalb wollte ich copy.deepcopy () verwenden, aber das funktioniert nicht mit SQLAlchemy. Jetzt bin ich in einem Dilemma, da ich bestimmte Attribute meines Objekts kopieren muss, bevor ich die iterativen Änderungen mache.

Zusammenfassend muss ich SQLAlchemy und gleichzeitig verwenden, um sicherzustellen, dass ich eine Kopie meiner Objektattribute haben kann, wenn ich Änderungen vornimmt, damit ich das referenzierte Objekt selbst nicht ändere.

Irgendwelche Ratschläge, Hilfe, Vorschläge usw.?

Edit: Habe etwas Code hinzugefügt.

%Vor%

Somit sind die Attribute, die ich ändern werde, die Attribute allocated_proj_ref und allocated_rank . Die students_table wird mit der eindeutigen Schüler-ID ( sid ) eingegeben.

Question

Ich möchte die Attribute beibehalten, die ich oben geändert habe - ich meine, das ist der Grund, warum ich mich für SQLA entschieden habe. Das gemappte Objekt wird sich jedoch ändern, was nicht empfohlen wird. Wenn ich also die Änderungen an doppelgänger, unmapped Objekt ... mache, kann ich diese Änderungen übernehmen und die Felder / Tabelle für das gemappte Objekt aktualisieren.

In gewissem Sinne befolge ich Davids sekundäre Lösung Ich erstelle eine andere Version der Klasse, die nicht zugeordnet ist.

Ich habe versucht, die unten angegebene StudentDBRecord -Lösung zu verwenden, habe aber einen Fehler bekommen!

%Vor%

Bedeutet dies, dass Student muss zugeordnet werden?

Health warning!

Jemand hat hier auf ein wirklich gutes zusätzliches Thema hingewiesen. Siehe, selbst wenn ich copy.deepcopy() für ein nicht zugeordnetes Objekt anrufe, nehmen wir in diesem Fall an, dass es das Schülerwörterbuch ist, das ich oben definiert habe, depecopy erstellt eine Kopie von alles . Mein allocated_proj_ref ist eigentlich ein Project Objekt und ich habe dafür ein entsprechendes projects Wörterbuch.

Also ich decopy sowohl students und projects - was ich bin - er sagt, dass ich Fälle haben werde, in denen das students s allocated_proj_ref Attribut Probleme mit dem Abgleich mit Instanzen in der% co_de haben wird % Wörterbuch.

Also nehme ich an, dass ich neu definieren / überschreiben muss (so heißt es, nicht wahr?) projects in jeder Klasse mit deepcopy oder so ähnlich?

Ich möchte def __deecopy__(self, memo): so überschreiben, dass es alle SQLA-Sachen ignoriert (die __deepcopy__ und <class 'sqlalchemy.util.symbol'> sind), aber kopiere alles andere, was Teil der a-map-Klasse ist.

Irgendwelche Vorschläge, bitte?

    
PizzAzzra 23.05.2017, 12:33
quelle

2 Antworten

1

Wenn ich mich richtig erinnere / denke, haben Sie normalerweise in SQLAlchemy immer nur ein Objekt, das einem bestimmten Datenbankeintrag entspricht. Dies wird getan, damit SQLAlchemy Ihre Python-Objekte mit der Datenbank synchronisieren kann und umgekehrt (na ja, nicht, wenn es gleichzeitige DB-Mutationen von außerhalb von Python gibt, aber das ist eine andere Geschichte). Das Problem ist also, dass Sie beim Kopieren eines dieser gemappten Objekte zwei unterschiedliche Objekte erhalten würden, die demselben Datenbankeintrag entsprechen. Wenn Sie eine ändern, hätten sie andere Werte und die Datenbank kann nicht beide gleichzeitig abgleichen.

Ich denke, Sie müssen möglicherweise entscheiden, ob der Datenbankeintrag die Änderungen widerspiegelt, die Sie vornehmen, wenn Sie ein Attribut Ihrer Kopie ändern. Wenn dies der Fall ist, sollten Sie die Objekte überhaupt nicht kopieren. Sie sollten nur dieselben Instanzen erneut verwenden.

Wenn Sie andererseits nicht möchten, dass sich der ursprüngliche Datenbankeintrag beim Aktualisieren der Kopie ändert, haben Sie eine andere Wahl: Sollte die Kopie eine neue Zeile in der Datenbank werden? Oder sollte es überhaupt nicht zu einem Datenbankeintrag zugeordnet werden? Im ersten Fall können Sie den Kopiervorgang implementieren, indem Sie eine neue Instanz der gleichen Klasse erstellen und die Werte kopieren, so wie Sie das ursprüngliche Objekt erstellt haben. Dies würde wahrscheinlich in der Methode __deepcopy__() der von Ihnen zugeordneten SQLAlchemy-Klasse geschehen. Im letzteren Fall (keine Zuordnung) benötigen Sie eine separate Klasse, die alle die gleichen Felder enthält, aber nicht mit SQLAlchemy zugeordnet ist. Eigentlich wäre es wahrscheinlich sinnvoller, wenn Ihre SQLAlchemy-abgebildete Klasse eine Unterklasse dieser nicht zugeordneten Klasse wäre und nur die Zuordnung für die Unterklasse.

BEARBEITEN : OK, um zu verdeutlichen, was ich mit dem letzten Punkt gemeint habe: Im Moment haben Sie eine Klasse Student , die Ihre Schüler repräsentiert. Ich schlage vor, dass Sie Student eine nicht zugeordnete reguläre Klasse erstellen:

%Vor%

und haben eine Unterklasse, etwa StudentDBRecord , die der Datenbank zugeordnet wird.

%Vor%

Nun würden Sie Ihren Optimierungsalgorithmus mit Instanzen von Student implementieren, die nicht zugeordnet sind. Wenn sich also die Attribute der Student -Objekte ändern, passiert nichts mit der Datenbank. Dies bedeutet, dass Sie copy oder deepcopy nach Bedarf verwenden können. Wenn Sie fertig sind, können Sie die Student -Instanzen in StudentDBRecord -Instanzen ändern, etwa wie

%Vor%

Dies wird gemappte Objekte erstellen, die allen Ihren Schülern in ihrem optimalen Zustand entsprechen und sie an die Datenbank binden.

EDIT 2 : Vielleicht funktioniert das nicht. Eine schnelle Lösung wäre, den Student -Konstruktor in StudentDBRecord zu kopieren und stattdessen StudentDBRecord extend object zu kopieren. Das heißt, ersetzen Sie die vorherige Definition von StudentDBRecord durch diese:

%Vor%

Oder wenn Sie es verallgemeinern wollten:

%Vor%

Diese letztere Definition kopiert alle nicht-speziellen Eigenschaften von Student auf StudentDBRecord .

    
David Z 06.06.2010, 06:16
quelle
2

Hier ist eine weitere Option, aber ich bin mir nicht sicher, ob sie auf Ihr Problem anwendbar ist:

  1. Abrufen von Objekten aus der Datenbank mit allen erforderlichen Beziehungen. Sie können lazy='joined' oder lazy='subquery' entweder an relations weitergeben oder die Methode options(eagerload(relation_property) der Abfrage aufrufen oder einfach auf die erforderlichen Eigenschaften zugreifen, um ihre Ladung auszulösen.
  2. Das Objekt aus der Sitzung entfernen. Das verzögerte Laden von Objekteigenschaften wird ab diesem Zeitpunkt nicht unterstützt.
  3. Jetzt können Sie das Objekt sicher ändern.
  4. Wenn Sie das Objekt in der Datenbank aktualisieren müssen, müssen Sie es wieder in Sitzung und Commit einfügen.

Update : Hier ist das Code-Beispiel zum Nachweis des Konzepts:

%Vor%     
Denis Otkidach 07.06.2010 17:09
quelle

Tags und Links