Python class 在每次调用时继承单例初始化实例

Python class inherited singleton inits instance on every call

我正在尝试实现 class 所描述的继承单例 here (Method 2). Going over the question and the extensive chosen answer 我试图实现以下内容:

class Singleton(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not isinstance(cls._instance, cls):
            cls._instance = object.__new__(cls, *args, **kwargs)
            cls._instance._initialized = False

        return cls._instance

class A(Singleton):
    def __init__(self):
        print "Init is called"

class B(Singleton):
    def __init__(self):
        print "Init is called"

您可能猜到了,每当我创建 Class A 时,我都会得到相同的对象,但会调用 __init__。这是有问题的,因为 Class A 可能因此更改其所有成员。

正在做:

a1 = A()
a2 = A()
print a1 == a2

将导致:

>> Init is called
>> Init is called
>> True

This question poses a similar issue but I would prefer not to use the solution there as it doesn't include the inheritance and I have at least 2 classes that needs the Singleton inheritance. I tried to implement the solution here but it didn't work. The solution here 有效,但它涉及更改 Class AClass B,我不想这样做。

有没有办法更改 Singleton 实现,这样 __init__ 就不会在每次创建时都被调用? (我不能使用 metaclasses,因为 AB 都继承了其他 classes,例如抽象 classes 和它们自己的 metaclasses).

谢谢

在现代 Python 中,这可以通过编写一个 __init_subclass__ 方法来完成,该方法可以装饰 __init__ 使其在 运行 之前检查 cls._instance

照原样,(即你也需要 Python 2) - 我认为更简单的事情是 __new__ 用 NOP 方法修补 __init__ 如果实例已存在:


_nop_init = lambda self, *args, **kw: None

class Singleton(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not isinstance(cls._instance, cls):
            cls._instance = object.__new__(cls, *args, **kwargs)
            cls._instance._initialized = False
        # Python 2 have to check in the cls.__dict__ - Py3 could check the attribute directly:
        elif cls.__dict__.get("__init__", None) is not _nop_init:
            cls.__init__ = _nop_init
        return cls._instance

class A(Singleton):
    def __init__(self):
        print "Init is called"

class B(Singleton):
    def __init__(self):
        print "Init is called"

额外信息调用__init__的语言机制内置于type__call__方法中-元class 对于 Python 中的所有 classes。它会在实例化时调用目标 class 的 __new____init__ 方法,因此,使用 metaclass,很容易从自定义对象控制这些调用元class。有趣的是,当 __new__ 不 return 时,目标 class 的实例不会被调用。 (在这个单例中,单例 te class 的一个实例,因此它被称为。

真实世界示例:上次我编写单例代码时,我选择避免在其自己的代码中重新运行 __init__ - 正弦它是项目中唯一的单例,在 __new__ 中不需要通用代码: https://github.com/jsbueno/pythonchain/blob/1f9208dc8bd2741a574adc1bf745d218e4314e4a/pythonchain/block.py#L276