2012-05-31 11 views
9

nehme an, ich habe eine einfache Python Klassendefinition in einer Datei myClass.pyPickle mit benutzerdefinierten Klassen

class Test: 
    A = [] 

Und ich habe auch zwei Testskripte. Das erste Skript erstellt ein Objekt vom Typ Test, füllt das Array A auf und packt das Ergebnis in eine Datei. Es entpackt es sofort aus der Datei und das Array ist immer noch gefüllt. Das zweite Skript wird einfach aus der Datei entfernt und das Array wird nicht aufgefüllt (d. H. A == []). Warum ist das?

test1.py

import myClass 
import pickle 

x = myClass.Test() 

for i in xrange(5): 
    x.A.append(i) 

f = open('data', 'w') 
pickle.dump(x,f) 
f.close() 

f = open('data') 
y = pickle.load(f) 
f.close 

print y.A 

und test2.py

import myClass 
import pickle 

f = open('data') 
y = pickle.load(f) 
f.close 

print y.A 

Antwort

14

Es ist, weil Sie Test.A als Klassenattribut anstelle einer Instanz Attribut festlegen. Wirklich, was passiert, ist, dass mit test1.py das Objekt, das aus der Beizdatei zurückgelesen wird, dasselbe ist wie test2.py, aber es verwendet die Klasse im Speicher, wo Sie ursprünglich x.A zugewiesen hatten.

Wenn Ihre Daten aus der Datei entfernt werden, erstellt sie eine neue Instanz des Klassentyps und wendet dann die erforderlichen Instanzdaten an. Aber deine einzigen Daten waren ein Klassenattribut. Es bezieht sich immer auf die Klasse im Speicher, die Sie in einer, aber nicht in einer anderen Datei geändert haben.

Vergleichen Sie die Unterschiede in diesem Beispiel:

class Test: 
    A = [] # a class attribute 
    def __init__(self): 
     self.a = [] # an instance attribute 

Sie werden feststellen, dass die Instanz Attribut a wird gebeizt und richtig ungebeizt, während das Klassenattribut A wird einfach auf die Klasse im Speicher verweisen.

for i in xrange(5): 
    x.A.append(i) 
    x.a.append(i) 

with open('data', 'w') as f: 
    pickle.dump(x,f) 

with open('data') as f: 
    y = pickle.load(f) 

>>> y.A 
[0, 1, 2, 3, 4] 
>>> y.a 
[0, 1, 2, 3, 4] 
>>> Test.A 
[0, 1, 2, 3, 4] 
>>> Test.A = [] # resetting the class attribute 
>>> y.a 
[0, 1, 2, 3, 4] 
>>> y.A # refers to the class attribute 
[] 
+0

Bedeutet dies, dass, wenn Sie die Klasse selbst gebeizt hatte, 'pickle.dump (Test)' und ungebeizte dann die Klasse, würden Sie die richtige Liste 'A' in beiden Fällen zurück bekommen haben? – BallpointBen

+0

@BallpointBen, nein, es würde nicht das Klassenattribut erhalten, wie [was-kann-pickled-and-unpickled] (https://docs.python.org/3/library/pickle.html#what- can-pickled-and-pickled): "Klassen werden nach benanntem Verweis gebeizt, daher gelten die gleichen Einschränkungen in der Umgebung für nicht entkoppelten Zugriff. Beachten Sie, dass der Code oder die Daten der Klasse nicht aktiviert sind." – jdi

Verwandte Themen