2016-04-17 4 views
5

Die documentation for Pickle speziell sagt:Warum ruft Pickle nicht __new__ an, wie die Dokumentation sagt?

Instanzen eines neuen Stils der Klasse C verwenden erstellt:

obj = C.__new__(C, *args) 

Der Versuch, diesen Vorteil zu nehmen, habe ich eine Singleton erstellt mit keine Instanz-Attribute oder Methoden:

class ZeroResultSentinel(object): 
    instance = None 
    def __new__(cls, *args): 
     if not cls.instance: 
      cls.instance = super(ZeroResultSentinel, cls).__new__(cls, *args) 
     return cls.instance 

(Diese Klasse in einer Caching-Schicht verwendet wird, ein nicht-Ergebnis Ergebnis her zu differenzieren m nichts im Cache.)

Der Singleton funktioniert hervorragend (jeder Aufruf von ZeroResultSentinel() führt zur gleichen Instanz im Speicher und ZeroResultSentinel() == ZeroResultSentinel() ergibt True). Und ich kann picken und die Instanz ohne Fehler entfernen. Wenn ich es jedoch abziehe, bekomme ich eine andere Instanz. Also habe ich einen Breakpoint innerhalb __new__ platziert. Ich knalle den Haltepunkt jedes Mal, wenn ich ZeroResultSentinel() anrufen, aber ich trete nicht auf einen Haltepunkt, wenn ich ein eingelegtes ZeroResultSentinel abnehme. Dies steht in direktem Widerspruch zur Dokumentation. Tue ich etwas falsch oder ist die Dokumentation falsch?

+1

Welches Beizprotokoll geben Sie an? – user2357112

Antwort

3

Die Dokumentation nicht wirklich deutlich machen, aber Ihre __new__ Methode wird nur für Gurke Protokoll 2 und höher verwendet werden:

>>> class Foo(object): 
...  def __new__(cls): 
...   print "New" 
...   return object.__new__(cls) 
... 
>>> foo = Foo() 
New 
>>> pickle.loads(pickle.dumps(foo, protocol=0)) 
<__main__.Foo object at 0x00000000025E9A20> 
>>> pickle.loads(pickle.dumps(foo, protocol=2)) 
New 
<__main__.Foo object at 0x00000000022A3F60> 

Auf Python 2, das Standardprotokoll 0 ist, also, wenn Sie‘ Um den Standardwert zu verwenden, müssen Sie dies ändern.

+0

Nun, schält. Ich habe bestätigt, dass es behoben wird. Aber wir sind auf einer sehr alten Version von Django, die das Protokoll für das Cache-Backend nicht spezifiziert, also kann ich nichts tun, bis wir upgraden. Wie _does_ Pickle erstellt eine Instanz in früheren Protokollen, wenn nicht '__new__' verwendet wird? –

+0

Korrektur: Das hat nichts mit Django zu tun. Wir sind nur auf Gedeih und Verderb einer Cachebibliothek, die das Beizen durchführt, ohne ein Protokoll anzugeben –

+0

Ich konnte ''pickleProtocol': pickle.HIGHEST_PROTOCOL' zu den Konfigurationseinstellungen für unser Cachebackending hinzufügen, um dies zum Laufen zu bringen. Vielen Dank für die Hilfe! (Ich bin immer noch neugierig, wenn Sie eine Minute haben, _how_ Pickle kann eine Instanz eines Objekts ohne Aufruf von '__new__' erstellen.) –

Verwandte Themen