2012-05-31 10 views
9

Supongamos que tengo una definición simple clase de Python en un archivo myClass.pyla salmuera de clases personalizadas

class Test: 
    A = [] 

Y también tengo dos scripts de prueba. La primera secuencia de comandos crea un objeto de tipo Prueba, rellena la matriz A y guarda el resultado en un archivo. Inmediatamente lo deshace del archivo y la matriz todavía está poblada. La segunda secuencia de comandos simplemente se desmarca del archivo y la matriz no está poblada (es decir, A == []). ¿Por qué es esto?

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 

y test2.py

import myClass 
import pickle 

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

print y.A 

Respuesta

14

Se debe a que se está configurando Test.A como un atributo de clase en lugar de un atributo de instancia. Realmente lo que está sucediendo es que con el test1.py, el objeto que se lee desde el archivo pickle es el mismo que test2.py, pero está usando la clase en la memoria donde originalmente asignó x.A.

Cuando sus datos se están deshaciendo del archivo, crea una nueva instancia del tipo de clase y luego aplica los datos de instancia que necesita. Pero tu único dato era un atributo de clase. Siempre se refiere a la clase que está en la memoria, que se modificó en uno, pero no en otro archivo.

comparar las diferencias en este ejemplo:

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

Usted se dará cuenta de que la instancia de atributos a se escabeche y unpickled correctamente, mientras que el atributo de clase A simplemente referirse a la clase en la 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

¿Quiere decir esto que si se hubiera conservado en vinagre la propia clase, 'pickle.dump (Prueba)', y luego unpickled la clase, se habría conseguido la lista correcta 'A' atrás en ambos casos? – BallpointBen

+0

@BallpointBen, no, no preservaría el atributo de clase, según [what-can-be-pickled-and-unpickled] (https://docs.python.org/3/library/pickle.html#what- can-be-pickled-and-unpickled): "las clases se decaparán por referencia nombrada, por lo que se aplican las mismas restricciones en el entorno de desapilado. Tenga en cuenta que ninguno de los códigos o datos de la clase está encurtido" – jdi

Cuestiones relacionadas