You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 21:40:35