Python单例模式实现报错:'NoneType'对象无'file'属性
解决Singleton模式中
'NoneType' object has no attribute 'file'异常 错误原因分析
1. 类属性拼写错误
在你的第一份代码的__str__方法中,出现了拼写错误:将类属性_INSTANCE误写为_INSTANCIA:
def __str__(self) -> str: ''' Returns file content ''' Logger._INSTANCIA.file.seek(0) # 错误拼写:_INSTANCIA → _INSTANCE return Logger._INSTANCE.file.read()
未定义的类属性会返回None,调用None.file自然触发'NoneType' object has no attribute 'file'异常。
2. 单例实例赋值错误
在__init__方法中,你将实例赋值给了实例属性self._INSTANCE,而非单例核心的类属性Logger._INSTANCE:
def __init__(self) -> None: if Logger._INSTANCE == None: self.file = open('./logfile.txt', 'a+') self._INSTANCE = self # 错误:应赋值给类属性 Logger._INSTANCE
类的_INSTANCE是单例的唯一标识,只有赋值给类属性,后续创建实例时才能检测到已有实例,同时log、__str__等方法都依赖Logger._INSTANCE,如果类属性未被正确赋值,它始终为None,调用Logger._INSTANCE.file必然报错。
修正后的代码
from __future__ import annotations from datetime import datetime as time class Logger: ''' Singleton class ''' _INSTANCE: Logger = None def __init__(self) -> None: if Logger._INSTANCE is None: self.file = open('./logfile.txt', 'a+') Logger._INSTANCE = self # 修正:赋值给类属性 def log(self, message: str) -> None: ''' Send message to file ''' Logger._INSTANCE.file.write(f'{time.now()}\t{message}\n') def __str__(self) -> str: ''' Returns file content ''' Logger._INSTANCE.file.seek(0) # 修正拼写错误 return Logger._INSTANCE.file.read() def __del__(self) -> None: ''' Close file at the end ''' Logger._INSTANCE.file.close() # Test if __name__ == '__main__': a = Logger() a.log('Logging from A') b = Logger() b.log('Logging from B') c = Logger() c.log('Logging from C') print(a)
额外优化建议
- 判断
None时,推荐使用is None而非== None,这是Python的最佳实践。 - 更标准的单例实现方式是重写
__new__方法(__init__是实例初始化方法,每次调用Logger()都会执行它,而__new__负责创建实例,能确保仅生成一个实例):
from __future__ import annotations from datetime import datetime as time class Logger: ''' Singleton class ''' _INSTANCE: Logger = None def __new__(cls) -> Logger: if cls._INSTANCE is None: cls._INSTANCE = super().__new__(cls) cls._INSTANCE.file = open('./logfile.txt', 'a+') return cls._INSTANCE def log(self, message: str) -> None: ''' Send message to file ''' self.file.write(f'{time.now()}\t{message}\n') def __str__(self) -> str: ''' Returns file content ''' self.file.seek(0) return self.file.read() def __del__(self) -> None: ''' Close file at the end ''' self.file.close()
内容的提问来源于stack exchange,提问作者MarCordero385
相关产品推荐
相关产品推荐

