Error during unpickling in python. AttributeError: 'Airthematic' object has no attribute '__addition'
Error during unpickling in python. AttributeError: 'Airthematic' object has no attribute '__addition'
下面是示例代码,我pickle成功了,但是unpickling报错。任何人都知道原因或解决方案将不胜感激。
sample.py
import pandas as pd
class Airthematic(object):
def __init__(self, symbol):
self.symbol_ = symbol
self.__x = None
self.__y = None
self.__result = None
self.__function_mapping = {
"+": self.__addition,
"-": self.__subtraction,
"*": self.__multiplication
}
def calculate(self, x, y):
self.__x = x
self.__y = y
self.__result = self.__function_mapping[self.symbol_]()
def __addition(self):
return self.__x+self.__y
def __subtraction(self):
return self.__x-self.__y
def __multiplication(self):
return self.__x*self.__y
@property
def first_number_(self):
return self.__x
@property
def second_number_(self):
return self.__y
@property
def result_(self):
return self.__result
这是juypter中的代码
from sample import Airthematic
a = Airthematic("+")
a.calculate(5, 6)
pd.to_pickle(a, "../output/sample.pickle") # Successful
aa = pd.read_pickle("../output/sample.pickle") # Giving error
AttributeError: 'Airthematic' 对象没有属性 '__addition'
不知何故包含函数映射的字典出错。
正如@IainShelvington 所解释的那样,私有属性和函数名称是不同的。所以我腌制后,用记事本打开文件观察了一下。我发现私有属性名保存为_Airthematic__x、_Airthematic__y等。但是函数名称没有存储,因为它存储为属性 _Airthematic__function_mapping 的 __multiplication。此外,在阅读@ewong 共享的文档后,我注意到函数名称未保存在 pickle 文件中。因此,当 unpickling 时,它会发现名为 __multiplication 的属性,该属性不存在于 pickle 文件中,因为未存储函数名称。所以我找到了解决方案,必须实现“__getstate__”和“__setstate__”功能。下面是修改后的版本,可以正常工作。
import pandas as pd
class Airthematic(object):
def __init__(self, symbol):
self.symbol_ = symbol
self.__x = None
self.__y = None
self.__result = None
self.__function_mapping = {
"+": self.__addition,
"-": self.__subtraction,
"*": self.__multiplication
}
def __getstate__(self):
state = self.__dict__.copy()
# Remove the unpicklable entries.
del state["_" + str(self.__class__.__name__) + '__function_mapping']
return state
def __setstate__(self, state):
# Restore instance attributes (i.e., function_mapping).
self.__dict__.update(state)
self.__function_mapping = {
"+": self.__addition,
"-": self.__subtraction,
"*": self.__multiplication
}
def calculate(self, x, y):
self.__x = x
self.__y = y
self.__result = self.__function_mapping[self.symbol_]()
def __addition(self):
return self.__x+self.__y
def __subtraction(self):
return self.__x-self.__y
def __multiplication(self):
return self.__x*self.__y
@property
def first_number_(self):
return self.__x
@property
def second_number_(self):
return self.__y
@property
def result_(self):
return self.__result
下面是示例代码,我pickle成功了,但是unpickling报错。任何人都知道原因或解决方案将不胜感激。
sample.py
import pandas as pd
class Airthematic(object):
def __init__(self, symbol):
self.symbol_ = symbol
self.__x = None
self.__y = None
self.__result = None
self.__function_mapping = {
"+": self.__addition,
"-": self.__subtraction,
"*": self.__multiplication
}
def calculate(self, x, y):
self.__x = x
self.__y = y
self.__result = self.__function_mapping[self.symbol_]()
def __addition(self):
return self.__x+self.__y
def __subtraction(self):
return self.__x-self.__y
def __multiplication(self):
return self.__x*self.__y
@property
def first_number_(self):
return self.__x
@property
def second_number_(self):
return self.__y
@property
def result_(self):
return self.__result
这是juypter中的代码
from sample import Airthematic
a = Airthematic("+")
a.calculate(5, 6)
pd.to_pickle(a, "../output/sample.pickle") # Successful
aa = pd.read_pickle("../output/sample.pickle") # Giving error
AttributeError: 'Airthematic' 对象没有属性 '__addition'
不知何故包含函数映射的字典出错。
正如@IainShelvington 所解释的那样,私有属性和函数名称是不同的。所以我腌制后,用记事本打开文件观察了一下。我发现私有属性名保存为_Airthematic__x、_Airthematic__y等。但是函数名称没有存储,因为它存储为属性 _Airthematic__function_mapping 的 __multiplication。此外,在阅读@ewong 共享的文档后,我注意到函数名称未保存在 pickle 文件中。因此,当 unpickling 时,它会发现名为 __multiplication 的属性,该属性不存在于 pickle 文件中,因为未存储函数名称。所以我找到了解决方案,必须实现“__getstate__”和“__setstate__”功能。下面是修改后的版本,可以正常工作。
import pandas as pd
class Airthematic(object):
def __init__(self, symbol):
self.symbol_ = symbol
self.__x = None
self.__y = None
self.__result = None
self.__function_mapping = {
"+": self.__addition,
"-": self.__subtraction,
"*": self.__multiplication
}
def __getstate__(self):
state = self.__dict__.copy()
# Remove the unpicklable entries.
del state["_" + str(self.__class__.__name__) + '__function_mapping']
return state
def __setstate__(self, state):
# Restore instance attributes (i.e., function_mapping).
self.__dict__.update(state)
self.__function_mapping = {
"+": self.__addition,
"-": self.__subtraction,
"*": self.__multiplication
}
def calculate(self, x, y):
self.__x = x
self.__y = y
self.__result = self.__function_mapping[self.symbol_]()
def __addition(self):
return self.__x+self.__y
def __subtraction(self):
return self.__x-self.__y
def __multiplication(self):
return self.__x*self.__y
@property
def first_number_(self):
return self.__x
@property
def second_number_(self):
return self.__y
@property
def result_(self):
return self.__result