Python类继承了每个

2024-06-17 06:56:29 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图实现类继承的单例,如here(方法2)所述。回顾这个问题和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提出了一个类似的问题,但是我不想使用那里的解决方案,因为它不包括继承,而且我至少有2个类需要Singleton继承。我试图实现解决方案here,但没有成功。solution here是可行的,但它涉及到改变Class AClass B,我不希望这样

有没有办法改变Singleton实现,这样__init__就不会在每次创建时都被调用(我不能使用元类,因为AB继承了其他类(例如,带有自己元类的抽象类)

谢谢


Tags: instancenewhereobjectinitisdefargs
1条回答
网友
1楼 · 发布于 2024-06-17 06:56:29

在现代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__的语言机制内置于__call__方法type中,该方法是Python中所有类的元类。实例化目标类时,它将调用目标类的__new____init__方法,因此,使用元类,可以很容易地从自定义元类控制这些调用。还值得注意的是,当__new__不返回目标类的实例时,不会调用__init__(在这种单例情况下,单例是te类的一个实例,因此它被称为

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

相关问题 更多 >