Ich habe ein Objekt, das nach der ersten Verwendung zwischengespeichert wird. Ich werde dies mit dem cPickle-Modul tun. Wenn das Modul bereits zwischengespeichert ist, wenn ich versuche, das Objekt das nächste Mal instanziieren (in einem anderen Prozess) möchte ich das zwischengespeicherte Objekt verwenden. meine Grundstruktur folgend:Das Entnehmen des Objekts vom Typ X in der Methode __new__ der Klasse X ruft __init__ beim Zurückgeben des nicht gepackten Objekts auf, warum?
import cPickle
class Test(object):
def __new__(cls, name):
if name == 'john':
print "using cached object"
with open("cp.p", "rb") as f:
obj = cPickle.load(f)
print "object unpickled"
return obj
else:
print "using new object"
return super(Test, cls).__new__(cls, name)
def __init__(self, name):
print "calling __init__"
self.name = name
with open("cp.p", "wb") as f:
cPickle.dump(self, f)
Das Problem ist, dass, wenn ich die im Cache gespeicherte Objekt in der __new__
Methode unpickle den __init__
nennt und neu initialisiert alles. Interessanterweise scheint die __init__
nicht nach dem unpickling aufgerufen zu werden, sondern eher wenn das unpickled Objekt zurückgegeben wird. Ich habe eine print-Anweisung hinzugefügt, die das anzeigt ("object unpickled").
Ich habe eine Hacky Abhilfe durch den folgenden Scheck an die __init__
fügen hinzu:
intiailzed = False
...
...
def __init__(self, name):
if not self.intialized:
self.initialized = True
# Rest of the __init__ here
Neben ein Klassenattribut initialisiert genannt, aber das ist natürlich nicht ideal.
Jeder Einblick, wie die __init__
Methode unterdrückt werden kann (oder warum es überhaupt aufgerufen wird) würde geschätzt.
Edit: basierend auf Feedback hier ist meine neue vorgeschlagene Lösung:
class Test(object):
def __new__(cls, name=None):
print "calling __new__"
if name == 'john':
print "using cached object"
with open("cp.p", "rb") as f:
obj = cPickle.load(f)
print "object unpickled"
return obj
else:
print "using new object"
obj = super(Test, cls).__new__(cls, name)
obj.initialize(name)
return obj
def __init__(self, name):
pass
def initialize(self, name):
print "calling __init__"
self.name = name
with open("cp.p", "wb") as f:
cPickle.dump(self, f)
In den Dokumenten [[If __new __() gibt eine Instanz von cls zurück, dann wird die Methode __init __() der neuen Instanz aufgerufen]] (https://docs.python.org/2/reference/datamodel.html #object .__ new__) – unutbu
Pro [Vereinheitlichende Typen und Klassen in Python 2.2] (https://www.python.org/download/releases/2.2.3/descrintro/#__new__), "die unveränderlichen Typen haben einen Dummy" __init__ ', während die veränderbaren Typen einen Dummy' __new__' haben. Wenn Sie nicht einen guten Grund haben (und ich weiß nichts davon), sollten auch Ihre Klassen dem gleichen Muster folgen. – unutbu
Dies war nur eine vereinfachte Verallgemeinerung von dem, was ich eigentlich habe, um meinen Punkt zu erleichtern, die Bedingungen sind sehr unterschiedlich. Danke für den Tipp, obwohl es wahrscheinlich keine schlechte Sache ist, es scheitern zu lassen, wenn man bedenkt, ob meine Bedingung erfüllt ist und die Datei nicht existiert, würde ich wollen, dass sie fehlschlägt. –