繁体   English   中英

为什么 singleton 类的 __init__() 方法被调用了两次?

[英]Why is singleton class' __init__() method called twice?

为什么foo被打印两次?

class A:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self, *, var):
        print('foo')
        self.var = var

a = A(var=1)
b = A(var=2)

assert a == b
assert a.var == b.var

当您编写A(...)时,您正在调用

type.__call__(A, ...)

那是因为typeA的元类。 type.__call__将依次调用__new____init__ 如果__new__返回 class 的实例,则将始终调用__init__ 这是一个简化的视图:

def __call__(cls, *args, **kwargs):
    self = cls.__new__(cls, *args, **kwargs)
    if isinstance(self, cls):
        cls.__init__(self, *args, **kwargs)
    return self

我能想到的让 singleton 以这种方式工作的最简单方法是将所有初始化逻辑放入__new__

class A:
    _instance = None

    def __new__(cls, *, var):
        if cls._instance is None:
            self = super().__new__(cls)
            self.var = var
            cls._instance = self

        return cls._instance

    def __init__(self, *args, **kwargs):
        print('foo')

当然,每次你请求一个新实例时, foo仍然会被打印出来,但它确实是一个 singleton。

更全面的方法是覆盖元类__call__方法的行为。 这将避免调用__init__除了一次:

class Singleton(type):
    def __call__(cls, *args, **kwargs):
        if hasattr(cls, '_instance'):
            return cls._instance
        return super().__call__(*args, **kwargs)

class A(metaclass=Singleton):
    def __init__(self, *, var):
        print('foo')
        self.var = var

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM