2012-05-31 12 views
9

Supponiamo che io sono un semplice definizione di classe Python in un file myClass.pyPickle con classi personalizzate

class Test: 
    A = [] 

e ho anche due script di test. Il primo script crea un oggetto di tipo Test, popola l'array A e mette il risultato in un file. Lo deseleziona immediatamente dal file e l'array è ancora popolato. Il secondo script designa solo il file e l'array non è popolato (ad esempio A == []). Perchè è questo?

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 

e test2.py

import myClass 
import pickle 

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

print y.A 

risposta

14

È perché si sta impostando Test.A come un attributo di classe, invece di un attributo di istanza. In realtà ciò che sta accadendo è che con test1.py, l'oggetto che viene riletto dal file pickle è lo stesso di test2.py, ma sta usando la classe in memoria a cui era stato assegnato originariamente x.A.

Quando i dati vengono annullati dal file, crea una nuova istanza del tipo di classe e quindi applica i dati di istanza necessari. Ma i tuoi soli dati erano un attributo di classe. Fa sempre riferimento alla classe che è in memoria, che hai modificato in uno, ma non in un altro file.

confrontare le differenze in questo esempio:

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

Si noterà che l'istanza attributo sarà salamoia a e deserializzato correttamente, mentre l'attributo class A semplicemente fare riferimento alla classe in memoria.

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

Questo significa che se si fosse in salamoia la classe stessa, 'pickle.dump (Test)', e quindi deserializzato la classe, si avrebbe ottenuto l'elenco corretto 'A' indietro in entrambi i casi? – BallpointBen

+0

@BallpointBen, no non conserverebbe l'attributo class, come per [what-can-be-pickled-and-unpickled] (https://docs.python.org/3/library/pickle.html#what- can-be-pickled-and-unpickled): "le classi vengono decapate in base al riferimento nominato, quindi si applicano le stesse restrizioni nell'ambiente di disimpegno. Nota che nessuno dei codici o dei dati della classe viene messo in salamoia" – jdi

Problemi correlati