Gibt es einen Kopierkonstruktor in python? Wenn nicht, was würde ich tun, um etwas Ähnliches zu erreichen?
Die Situation ist, dass ich eine Bibliothek verwende und eine der Klassen dort um zusätzliche Funktionen erweitert habe und die Objekte, die ich aus der Bibliothek erhalte, in Instanzen meiner eigenen Klasse konvertieren möchte.
Ich denke du willst das Kopiermodul
import copy
x = copy.copy(y) # make a shallow copy of y
x = copy.deepcopy(y) # make a deep copy of y
sie können das Kopieren auf die gleiche Weise steuern wie pickle .
In python kann der Kopierkonstruktor mit Standardargumenten definiert werden. Nehmen wir an, Sie möchten, dass der normale Konstruktor die Funktion non_copy_constructor(self)
ausführt und der Kopierkonstruktor copy_constructor(self, orig)
. Dann können Sie Folgendes tun:
class Foo:
def __init__(self, orig=None):
if orig is None:
self.non_copy_constructor()
else:
self.copy_constructor(orig)
def non_copy_constructor(self):
# do the non-copy constructor stuff
def copy_constructor(self, orig):
# do the copy constructor
a=Foo() # this will call the non-copy constructor
b=Foo(a) # this will call the copy constructor
Ein einfaches Beispiel für meine übliche Implementierung eines Kopierkonstruktors:
import copy
class Foo:
def __init__(self, data):
self._data = data
@classmethod
def from_foo(cls, class_instance):
data = copy.deepcopy(class_instance._data) # if deepcopy is necessary
return cls(data)
In Ihrer Situation würde ich vorschlagen, eine Klassenmethode (oder eine statische Methode oder eine separate Funktion) zu schreiben, die eine Instanz der Klasse der Bibliothek als Argument verwendet und eine Instanz Ihrer Klasse mit allen anwendbaren Attributen zurückgibt, die kopiert wurden.
Aufbauend auf @ Godsmiths Gedankengang und Ansprechen von @ Zitrax 'Bedürfnis (glaube ich), die Daten für alle Attribute innerhalb des Konstruktors zu kopieren:
class ConfusionMatrix(pd.DataFrame):
def __init__(self, df, *args, **kwargs):
try:
# Check if `df` looks like a `ConfusionMatrix`
# Could check `isinstance(df, ConfusionMatrix)`
# But might miss some "ConfusionMatrix-elligible" `DataFrame`s
assert((df.columns == df.index).all())
assert(df.values.dtype == int)
self.construct_copy(df, *args, **kwargs)
return
except (AssertionError, AttributeError, ValueError):
pass
# df is just data, so continue with normal constructor here ...
def construct_copy(self, other, *args, **kwargs):
# construct a parent DataFrame instance
parent_type = super(ConfusionMatrix, self)
parent_type.__init__(other)
for k, v in other.__dict__.iteritems():
if hasattr(parent_type, k) and hasattr(self, k) and getattr(parent_type, k) == getattr(self, k):
continue
setattr(self, k, deepcopy(v))
Diese ConfusionMatrix
Klasse erbt ein pandas.DataFrame
und fügt eine Menge anderer Attribute und Methoden hinzu, die neu berechnet werden müssen, es sei denn, die Matrixdaten von other
können kopiert werden. Auf der Suche nach einer Lösung bin ich auf diese Frage gestoßen.
Ich habe eine ähnliche Situation, die sich darin unterscheidet, dass die neue Klasse nur Attribute kopieren muss. Auf diese Weise könnte @ meisterluks "copy_constructor" -Methode lauten:
from copy import deepcopy
class Foo(object):
def __init__(self, myOne=1, other=None):
self.two = 2
if other <> None:
assert isinstance(other, Foo), "can only copy instances of Foo"
self.__dict__ = deepcopy(other.__dict__)
self.one = myOne
def __repr__(self):
out = ''
for k,v in self.__dict__.items():
out += '{:>4s}: {}, {}\n'.format(k,v.__class__,v)
return out
def bar(self):
pass
foo1 = Foo()
foo2 = Foo('one', foo1)
print '\nfoo1\n',foo1
print '\nfoo2\n',foo2
Die Ausgabe:
foo1
two: <type 'int'>, 2
one: <type 'int'>, 1
foo2
two: <type 'int'>, 2
one: <type 'str'>, one