Mininet--log.py-单例日志器-super().__new__(cls)解析
1. Python 类的 __new__
方法
在 Python 中,__new__
是一个静态方法,负责创建类的实例。
- 默认行为:当定义一个类时,若未显式定义
__new__
方法,Python 会自动调用父类(通常是object
)的__new__
方法创建实例。 - 关键作用:
__new__
返回实例后,__init__
方法才会被调用以初始化实例。
2. super()
的行为解析
super()
函数用于调用父类(超类)的方法。- 在类的上下文中,
super()
会根据当前类的 方法解析顺序(MRO) 查找下一个父类。
示例代码:
class MyClass:
def __new__(cls, *args, **kwargs):
print("MyClass __new__ called")
return super().__new__(cls) # 调用父类的 __new__ 方法
obj = MyClass()
运行结果:
MyClass __new__ called
解析:
MyClass
没有显式继承其他类,因此默认父类是object
。super().__new__(cls)
等价于object.__new__(cls)
,即调用object
的__new__
方法创建实例。
3. 单例模式中的 __new__
方法覆盖
在单例模式中,我们需要覆盖 __new__
方法,以确保只创建一个实例。
示例代码:
class SingletonLogger:
_instance = None # 保存唯一实例
def __new__(cls, *args, **kwargs):
if not cls._instance:
# 调用父类的 __new__ 方法创建实例
cls._instance = super().__new__(cls)
cls._instance.init_logger() # 初始化日志配置
return cls._instance
def init_logger(self):
import logging
self.logger = logging.getLogger("SingletonLogger")
self.logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
self.logger.addHandler(handler)
def info(self, message):
self.logger.info(message)
关键点:
super().__new__(cls)
调用的是object.__new__(cls)
,因为SingletonLogger
的父类是object
。- 这一步实际完成了实例的物理创建(分配内存等操作)。
4. 为什么必须调用 super().__new__(cls)
?
- 实例的物理创建:Python 中对象的创建(内存分配)必须由
__new__
方法完成。 - 不调用父类
__new__
的后果:若在__new__
中不调用父类的方法,将无法生成有效的实例。例如:class BadSingleton: _instance = None def __new__(cls): if not cls._instance: # 错误!没有调用父类的 __new__,直接返回一个无效实例 cls._instance = object.__new__(cls) return cls._instance
- 此处
object.__new__(cls)
正确,但若完全忽略父类方法,会导致未定义行为。
- 此处
5. 对比元类实现与 __new__
覆盖实现
元类实现单例
class Singleton(type):
def __call__(cls, *args, **kwargs):
if not cls.instance:
cls.instance = super().__call__(*args, **kwargs)
return cls.instance
class MyClass(metaclass=Singleton):
pass
- 原理:通过元类的
__call__
方法拦截实例化请求,控制实例创建。 - 调用链:
MyClass()
→Singleton.__call__()
→type.__call__()
(实际创建实例)。
覆盖 __new__
方法实现单例
class SingletonClass:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
- 原理:在类的
__new__
方法中控制实例创建,直接返回已有实例。 - 调用链:
SingletonClass()
→SingletonClass.__new__()
→object.__new__()
。
6. 验证 super()
的父类指向
通过打印 super()
的信息,可以明确其指向的父类:
class Parent:
pass
class Child(Parent):
def __new__(cls, *args, **kwargs):
print("Child __new__ called")
print("super() in Child:", super())
return super().__new__(cls)
obj = Child()
输出:
Child __new__ called
super() in Child: <super: <class 'Child'>, <Child object>>
解析:
super()
在Child
类中指向的是Parent
类(因为Child
显式继承自Parent
)。- 若类没有显式继承,默认指向
object
。
总结
super().__new__(cls)
的作用:调用父类的__new__
方法完成实例的物理创建。- 父类的指向:
- 若类显式继承自某个父类(如
class MyClass(Parent)
),则super()
指向该父类。 - 若类没有显式继承(如
class MyClass
),则super()
默认指向object
。
- 若类显式继承自某个父类(如
- 单例模式的核心:无论通过元类还是覆盖
__new__
方法,核心逻辑都是控制实例的创建次数,确保全局唯一性。