2015-05-26 17 views
5

Lassen Sie uns sagen, ich habe eine Klasse wie folgt zu speichern: -Pickle Dump ein Objekt innerhalb der Klasse

class MyClass: 
    some object here 
    some other object here 
    def init(self, some parameters): 
    do something 
    def some_other_method(self, param): 
    something else 
    def save(self, path): 
    PICKLE DUMP THIS OBJECT 
    def load(self, path): 
    PICKLE LOAD OBJECT 

Ich will nicht Last Gurke und Dump wie:

obj = MyClass(param) 
pickle.dump(obj, mypath) 

aber eher wie folgt:

obj.save(mypath) 

Wie kann ich dies innerhalb der Klassendefinition tun?

+0

Was meinst du "irgendein Objekt hier"? Wie bringst du ein Objekt hinein? – BrenBarn

+0

@BrenBarn kann ein beliebiges Attribut der Klasse sein (kein Objekt derselben Klasse) – Aditya

+0

@AdityaJoshi: Nur um klar zu sein, nimmt 'pickle.dump' keinen String-Pfad an ... es braucht ein Datei-Handle (dh' f = offen (mein Weg, 'r') '). Das gleiche gilt für 'pickle.load'. –

Antwort

4

Sie können self statt obj übergeben. Mit anderen Worten:

def save(self, file_handler): 
    pickle.dump(self, file_handler) 

Die self verweist auf die Instanz dieser Klasse. Also, was Sie im Grunde tun, ist pickle.dump aufrufen und übergeben Sie die Instanz zusammen mit dem Argument file_handler.

+1

'dump' nimmt ein Datei-Handle und keinen Pfad. Während dieser Code funktioniert, wenn 'path' ein Datei-Handle ist, ist es irreführend. –

1

Wir bauen eine Klasse A, und versuchen Sie es ...

>>> class A(object): 
... x = 1 
... def __init__(self, y): 
...  self.y = y 
... def showme(self): 
...  return self.y + self.x 
... def save(self): 
...  return pickle.dump(self) 
... def load(self, pik): 
...  self.__dict__.update(pickle.loads(pik).__dict__) 
... 
>>> a = A(2) 
>>> a.showme() 
3 
>>> import pickle 
>>>   
>>> a_ = a.save() 
>>> a.y = 5 
>>> a.showme() 
6 
>>> a.load(a_) 
>>> a.y 
2 
>>> a.showme() 
3 
>>> b = A(9) 
>>> b.load(a_) 
>>> b.y 
2 
>>> b.showme() 
3 
>>> b.x = 4 
>>> b.showme() 
6 
>>> b_ = b.save() 
>>> a.load(b_) 
>>> a.x 
4 
>>> a.y 
2 
>>> a.showme() 
6 
>>> 

Da jedoch die Klasse in __main__ definiert, wenn Sie über den Python-Interpreter-Sitzung starten waren ... Ihre Gurken nutzlos wäre als die Klasse würde nicht mehr existieren. Das liegt daran, dass Python als Referenz verwendet wird. Es gibt jedoch einen Workaround dafür. Wenn Sie dill verwenden, können Sie Ihre Klassen durch das Serialisieren der Klassendefinition ebenfalls putzen. Dann sind die in __main__ definierten Klassen in einer neuen Sitzung verfügbar.

>>> a.showme() 
6 
>>> import dill as pickle 
>>> a.save() 
'\x80\x02cdill.dill\n_create_type\nq\x00(cdill.dill\n_load_type\nq\x01U\x08TypeTypeq\x02\x85q\x03Rq\x04U\x01Aq\x05h\x01U\nObjectTypeq\x06\x85q\x07Rq\x08\x85q\t}q\n(U\x04loadq\x0bcdill.dill\n_create_function\nq\x0c(cdill.dill\n_unmarshal\nq\rU\xaec\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00C\x00\x00\x00s \x00\x00\x00|\x00\x00j\x00\x00j\x01\x00t\x02\x00j\x03\x00|\x01\x00\x83\x01\x00j\x00\x00\x83\x01\x00\x01d\x00\x00S(\x01\x00\x00\x00N(\x04\x00\x00\x00t\x08\x00\x00\x00__dict__t\x06\x00\x00\x00updatet\x06\x00\x00\x00picklet\x05\x00\x00\x00loads(\x02\x00\x00\x00t\x04\x00\x00\x00selft\x03\x00\x00\x00pik(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00load\t\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x0e\x85q\x0fRq\x10c__builtin__\n__main__\nh\x0bNN}q\x11tq\x12Rq\x13U\r__slotnames__q\x14]q\x15U\n__module__q\x16U\x08__main__q\x17U\x06showmeq\x18h\x0c(h\rUuc\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\x0e\x00\x00\x00|\x00\x00j\x00\x00|\x00\x00j\x01\x00\x17S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x01\x00\x00\x00yt\x01\x00\x00\x00x(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x06\x00\x00\x00showme\x05\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x19\x85q\x1aRq\x1bc__builtin__\n__main__\nh\x18NN}q\x1ctq\x1dRq\x1eU\x01xq\x1fK\x01U\x04saveq h\x0c(h\rU{c\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00t\x00\x00j\x01\x00|\x00\x00\x83\x01\x00S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x06\x00\x00\x00picklet\x05\x00\x00\x00dumps(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00save\x07\x00\x00\x00s\x02\x00\x00\x00\x00\x01q!\x85q"Rq#c__builtin__\n__main__\nh NN}q$tq%Rq&U\x07__doc__q\'NU\x08__init__q(h\x0c(h\rUuc\x02\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00|\x01\x00|\x00\x00_\x00\x00d\x00\x00S(\x01\x00\x00\x00N(\x01\x00\x00\x00t\x01\x00\x00\x00y(\x02\x00\x00\x00t\x04\x00\x00\x00selfR\x00\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x08\x00\x00\x00__init__\x03\x00\x00\x00s\x02\x00\x00\x00\x00\x01q)\x85q*Rq+c__builtin__\n__main__\nh(NN}q,tq-Rq.utq/Rq0)\x81q1}q2(U\x01yq3K\x02h\x1fK\x04ub.' 
>>> 

Dann beenden wir die Sitzung und starten neu. Einfügen in die Schnur von oben. (Ja, das könnte ich mit einer Datei-Handle arbeiten, anstatt, aber ich werde die später ... zeigen)

Python 2.7.9 (default, Dec 11 2014, 01:21:43) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dill as pickle 
>>> 
>>> a = '\x80\x02cdill.dill\n_create_type\nq\x00(cdill.dill\n_load_type\nq\x01U\x08TypeTypeq\x02\x85q\x03Rq\x04U\x01Aq\x05h\x01U\nObjectTypeq\x06\x85q\x07Rq\x08\x85q\t}q\n(U\x04loadq\x0bcdill.dill\n_create_function\nq\x0c(cdill.dill\n_unmarshal\nq\rU\xaec\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00C\x00\x00\x00s \x00\x00\x00|\x00\x00j\x00\x00j\x01\x00t\x02\x00j\x03\x00|\x01\x00\x83\x01\x00j\x00\x00\x83\x01\x00\x01d\x00\x00S(\x01\x00\x00\x00N(\x04\x00\x00\x00t\x08\x00\x00\x00__dict__t\x06\x00\x00\x00updatet\x06\x00\x00\x00picklet\x05\x00\x00\x00loads(\x02\x00\x00\x00t\x04\x00\x00\x00selft\x03\x00\x00\x00pik(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00load\t\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x0e\x85q\x0fRq\x10c__builtin__\n__main__\nh\x0bNN}q\x11tq\x12Rq\x13U\r__slotnames__q\x14]q\x15U\n__module__q\x16U\x08__main__q\x17U\x06showmeq\x18h\x0c(h\rUuc\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\x0e\x00\x00\x00|\x00\x00j\x00\x00|\x00\x00j\x01\x00\x17S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x01\x00\x00\x00yt\x01\x00\x00\x00x(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x06\x00\x00\x00showme\x05\x00\x00\x00s\x02\x00\x00\x00\x00\x01q\x19\x85q\x1aRq\x1bc__builtin__\n__main__\nh\x18NN}q\x1ctq\x1dRq\x1eU\x01xq\x1fK\x01U\x04saveq h\x0c(h\rU{c\x01\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00t\x00\x00j\x01\x00|\x00\x00\x83\x01\x00S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x06\x00\x00\x00picklet\x05\x00\x00\x00dumps(\x01\x00\x00\x00t\x04\x00\x00\x00self(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x04\x00\x00\x00save\x07\x00\x00\x00s\x02\x00\x00\x00\x00\x01q!\x85q"Rq#c__builtin__\n__main__\nh NN}q$tq%Rq&U\x07__doc__q\'NU\x08__init__q(h\x0c(h\rUuc\x02\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00C\x00\x00\x00s\r\x00\x00\x00|\x01\x00|\x00\x00_\x00\x00d\x00\x00S(\x01\x00\x00\x00N(\x01\x00\x00\x00t\x01\x00\x00\x00y(\x02\x00\x00\x00t\x04\x00\x00\x00selfR\x00\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00s\x07\x00\x00\x00<stdin>t\x08\x00\x00\x00__init__\x03\x00\x00\x00s\x02\x00\x00\x00\x00\x01q)\x85q*Rq+c__builtin__\n__main__\nh(NN}q,tq-Rq.utq/Rq0)\x81q1}q2(U\x01yq3K\x02h\x1fK\x04ub.' 
>>> 
>>> pickle.loads(a) 
<__main__.A object at 0x105691c50> 
>>> b = _ 
>>> 
>>> b.x 
4 
>>> b.showme() 
6 
>>> A = b.__class__ 
>>> c = A(2) 
>>> c.x 
1 
>>> c.showme() 
3 

Unglaublich, wird die Klasse in __main__ aus der eingelegten Instanz wieder aufgebaut. Ok, also jetzt, lass uns die Klassenmethoden ändern, um einen neuen save und load zu verwenden, der mit Dateien statt Strings arbeitet.

>>> def save(self, path): 
... with open(path, 'w') as f:   
...  pickle.dump(self, f) 
... 
>>> def load(self, path): 
... with open(path, 'r') as f: 
...  self.__dict__.update(pickle.load(f).__dict__) 
... 
>>> A.save = save 
>>> A.load = load 
>>> 
>>> c.save('foo') 
>>> 

Dann beenden wir die Sitzung und starten neu. Da wir keine Version von A herumliegen haben, müssen wir die load Methode direkt von pickle (tatsächlich, dill in diesem Fall) verwenden.

Python 2.7.9 (default, Dec 11 2014, 01:21:43) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dill as pickle 
>>> with open('foo', 'r') as f: 
... a = pickle.load(f) 
... 
>>> a 
<__main__.A object at 0x1028c0b10> 
>>> a.x 
1 
>>> a.showme() 
3 
>>> a.y = 6 
>>> a.showme() 
7 
>>> a.load('foo') 
>>> a.y  
2 
>>> a.showme() 
3 
>>> 

Es könnte eine bessere oder speziellere Art und Weise sein, dass Sie den Zustand der Klasseninstanz laden möchten, anstatt die __dict__ aktualisieren. Dies funktioniert nicht in allen Fällen, und es ist wahrscheinlich besser, für Ihre Klasse anzupassen. Wäre es mir aber, würde ich save und load Methoden in der Klasse nicht haben, sondern würde die Methoden verwenden, die von Ihrem Serializer direkt bereitgestellt werden. Sie können oben sehen, wie peinlich/redundant es ist, die load Methode innerhalb der Klasse zu verwenden.

Verwandte Themen