使用pickle序列化Player类遇NoneType属性错误,如何解决?
解决Player类存档/读档的AttributeError问题
问题根源
- Path用法错误:原代码里
Path("_SaveFile.pkl", "rb").is_file()写法有误,Path的第二个参数不是文件打开模式,应该直接传入文件名创建路径对象。 - 无存档时返回None:当存档文件不存在时,
load方法没有明确返回值,默认返回None,导致player变量变成空对象,访问location属性时触发AttributeError。 - 调用逻辑冗余:
Player().load()先创建一个Player实例再调用加载方法,完全没必要——我们要的是加载存档里的实例,新建实例属于多余操作。
修复步骤
1. 修正基础错误并保证返回有效实例
先修复Path的错误,同时确保无论有没有存档,load方法都返回一个Player实例,避免返回None:
from pathlib import Path import pickle class Player: def __init__(self): self.name = "" self.location = "start" self.hp = 100 def save(self): pickle.dump(self, open("_SaveFile.pkl", "wb")) def load(self): # 修正Path的参数写法 if Path("_SaveFile.pkl").is_file(): with open("_SaveFile.pkl", "rb") as f: character = pickle.load(f) return character # 无存档时返回当前实例(或者新建实例) return self def isAlive(self): return self.hp > 0
2. 优化成更合理的类方法
把load改成类方法,不需要先创建实例就能调用,逻辑更清晰:
from pathlib import Path import pickle class Player: def __init__(self): self.name = "" self.location = "start" self.hp = 100 def save(self): pickle.dump(self, open("_SaveFile.pkl", "wb")) # 用@classmethod装饰器标记为类方法 @classmethod def load(cls): save_file = Path("_SaveFile.pkl") if save_file.is_file(): with open(save_file, "rb") as f: return pickle.load(f) # 无存档时直接返回新的Player实例 return cls() def isAlive(self): return self.hp > 0
调用时直接写:
player = Player.load()
3. 可选:增加异常处理提升健壮性
如果担心存档文件损坏,可以在load里捕获反序列化异常:
@classmethod def load(cls): save_file = Path("_SaveFile.pkl") if save_file.is_file(): try: with open(save_file, "rb") as f: return pickle.load(f) except (pickle.UnpicklingError, EOFError): print("存档损坏,将创建新角色") return cls()
验证效果
修改后调用Player.load(),无论是否存在存档,player都会是一个有效的Player实例:
- 有存档时,加载存档中的角色数据;
- 无存档或存档损坏时,创建默认初始角色;
此时访问player.location不会再触发AttributeError。
内容的提问来源于stack exchange,提问作者bigboibob
相关产品推荐
相关产品推荐

