首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python类在每次调用时都继承其实例中的单例。

Python类在每次调用时都继承其实例中的单例。
EN

Stack Overflow用户
提问于 2019-12-13 05:30:21
回答 1查看 510关注 0票数 0

我正在尝试实现类继承单例,如描述的这里 (方法2)。通过这个问题和广泛选择的答案,我尝试实现以下内容:

代码语言:javascript
复制
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可以因此而更改它的所有成员。

做:

代码语言:javascript
复制
a1 = A()
a2 = A()
print a1 == a2

将导致:

代码语言:javascript
复制
>> Init is called
>> Init is called
>> True

这个问题提出了一个类似的问题,但我不想在那里使用该解决方案,因为它不包括继承,而且至少有两个类需要Singleton继承。我试图实现解决方案这里,但它没有工作。解在这里可以工作,但它涉及更改Class AClass B,而我不希望它们改变。

是否有一种方法可以更改Singleton实现,使每个创建都不会调用__init__?(我不能同时使用元类作为AB继承其他类,例如使用自己的元类的抽象类)。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-13 19:02:29

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

实际上,(也就是Python2也需要它)--我认为,如果实例已经存在,__new__用NOP方法修补__init__是更简单的事情:

代码语言:javascript
复制
_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__方法中--是所有类的元类。在实例化目标类时,它将调用目标类的__new____init__方法,因此,通过元类,很容易从自定义元类控制这些调用。值得注意的是,当__new__不返回目标类的实例时,不会调用__init__。(在这个单例中,单例是te类的一个实例,因此被调用)。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59316642

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档