向Gesture类新增方法后,加载序列化实例出现AttributeError的解决办法
问题
在手势识别机器学习项目中,我创建了Gesture类,读取数据集后生成类实例存入列表,并用pickle序列化保存为.dat文件(避免重复加载耗时)。之后给Gesture类新增了Reframe_Sequence方法,但调用加载后的实例的该方法时,抛出AttributeError: 'Gesture' object has no attribute 'Reframe_Sequence'错误。是否必须重新保存数据集,还是有其他解决办法?
类及新增方法代码
class Gesture: def __init__(self, gesture, finger, subject, trial, sequence): self.gesture = gesture self.finger = finger self.subject = subject self.trial = trial self.sequence = sequence def Reframe_Sequence(self): # split each row by spaces, and save in an array # make an array that is len x 22 x 3 # loop through each frame, then nested loop through, each with step of 3 and add the xyz to the joint s = self.sequence.to_numpy() n = s.size #number of frames arr2D = np.zeros(n, 66) arr3D = np.zeros(n,22,3) for i in range(n): arr2D[i] = s[i].split(" ") for i in range(n): for j in range(0, 66, 3): arr3D[i,j/3] = arr2D[i,j:j+3] self.sequence = arr3D return self.sequence
加载及保存代码
rootdir = '/content/drive/MyDrive/Colab Notebooks/HandGestureDataset_SHREC2017' for subdir, dirs, files in os.walk(rootdir): for file in files: word = "skeletons_world.txt" if word in file: path = os.path.join(subdir, file) path_list = path.split("/") gesture = re.findall(r'\d+', path_list[6]) finger = re.findall(r'\d+', path_list[7]) subject= re.findall(r'\d+', path_list[8]) trial= re.findall(r'\d+', path_list[9]) sequence = pd.read_csv(path) g = Gesture(gesture, finger, subject, trial, sequence) Master_List.append(g) pickle.dump(Master_List, open("master_list.dat", "wb")) ML = pickle.load(open("/content/master_list.dat", "rb"))
报错代码及信息
m = ML[5] m.Reframe_Sequence() k = m.sequence print(k)
AttributeError Traceback (most recent call last) in () 1 m = ML[5] ----> 2 m.Reframe_Sequence() 3 k = m.sequence 4 print(k) AttributeError: 'Gesture' object has no attribute 'Reframe_Sequence'
解决方案
原因
pickle序列化保存的是实例创建时的类结构,当时的Gesture类还没有Reframe_Sequence方法,所以加载后的实例也不具备这个方法。
可选解决办法
重新序列化数据集(推荐)
直接重新运行生成Master_List并保存的代码,此时新创建的Gesture实例已经包含Reframe_Sequence方法,序列化后再加载就可以正常调用。这是最直观且不易出错的方式,适合数据集重新生成耗时不是极端长的场景。动态绑定方法(无需重新保存)
如果不想重新生成数据集,确保当前环境中已经定义好包含Reframe_Sequence方法的完整Gesture类,加载实例后,直接将方法绑定到类上,所有加载后的实例都会生效:ML = pickle.load(open("/content/master_list.dat", "rb")) # 绑定方法到类 Gesture.Reframe_Sequence = Gesture.Reframe_Sequence # 之后正常调用 m = ML[5] m.Reframe_Sequence()原理是pickle加载实例时,会将其关联到当前环境中的同名类,只要类结构兼容(仅新增方法属于兼容场景),就能直接使用新增的方法。
额外代码修复提示
你的Reframe_Sequence方法存在两处语法错误,需要修正才能正常运行:
np.zeros(n, 66)和np.zeros(n,22,3)需改为np.zeros((n, 66))、np.zeros((n,22,3))——多维数组的形状必须用元组传递arr3D[i,j/3]需改为arr3D[i,j//3]——数组索引必须是整数,用整数除法//替代浮点数除法/
内容的提问来源于stack exchange,提问作者Quill
相关产品推荐
相关产品推荐

