Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
单例python调用两次出现问题\uuu init___Python_Singleton_Init - Fatal编程技术网

单例python调用两次出现问题\uuu init__

单例python调用两次出现问题\uuu init__,python,singleton,init,Python,Singleton,Init,我有一个这样的单身汉 class Singleton: class __impl: def __init__(self): print "INIT" __instance = None def __init__(self): # Check whether we already have an instance if Singleton.__instance is None:

我有一个这样的单身汉

class Singleton:

    class __impl:
        def __init__(self):
            print "INIT"

    __instance = None

    def __init__(self):
        # Check whether we already have an instance
        if Singleton.__instance is None:
            Singleton.__instance = Singleton.__impl()

        # Store instance reference as the only member in the handle
        self.__dict__['_Singleton__instance'] = Singleton.__instance

    def __getattr__(self, attr):
        """ Delegate access to implementation """
        return getattr(self.__instance, attr)

    def __setattr__(self, attr, value):
        """ Delegate access to implementation """
        return setattr(self.__instance, attr, value)
当我做了几个Singleton实例时,我收到了两个调用init,我的意思是“init”被打印了两次,我认为这不应该发生


有人知道这有什么问题,或者有更好的方法来实现它???

这里有一个稍微简单的方法来编写一个单例:

class Singleton(object):
    __instance = None
    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super(Singleton,cls).__new__(cls)
            cls.__instance.__initialized = False
        return cls.__instance

    def __init__(self):      
        if(self.__initialized): return
        self.__initialized = True
        print ("INIT")

a = Singleton()
b = Singleton()
print (a is b)
尽管可能有更好的方法。我得承认我从来都不喜欢单身。我更喜欢工厂式方法:

class Foo(object):
    pass

def foo_singleton_factory(_singlton = Foo()):
    return _singleton

a = foo_singleton_factory()
b = foo_singleton_factory()
print (a is b)
这样做的好处是,如果您愿意,您可以继续获得相同的Foo实例,但如果您在10年后决定不想要真正的单实例,则不限于单个实例。

有一个类单实例装饰器的示例:

def singleton(cls):
    instances = {}
    def getinstance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return getinstance

@singleton
class MyClass:
    ...
(虽然我自己没用过。)

顺便说一句,关于

我做了一个这样的单身汉

class Singleton:

    class __impl:
        def __init__(self):
            print "INIT"

    __instance = None

    def __init__(self):
        # Check whether we already have an instance
        if Singleton.__instance is None:
            Singleton.__instance = Singleton.__impl()

        # Store instance reference as the only member in the handle
        self.__dict__['_Singleton__instance'] = Singleton.__instance

    def __getattr__(self, attr):
        """ Delegate access to implementation """
        return getattr(self.__instance, attr)

    def __setattr__(self, attr, value):
        """ Delegate access to implementation """
        return setattr(self.__instance, attr, value)
此外,您还应该提到您。

另一种方式:

>>> class Singleton(object):
...     def __new__(cls, *args, **kwargs):
...             try:
...                     return cls._instance
...             except AttributeError:
...                     val = cls._instance = object.__new__(cls, *args, **kwargs)
...                     return val
... 
>>> class A(Singleton): pass
... 
>>> a = A()
>>> a2 = A()
>>> a2 is a
True
>>> class B(Singleton): pass
... 
>>> b = B()
>>> b2 = B()
>>> b2 is b
True
>>> b is a
False
>>> class D(Singleton):
...     def __init__(self, v): self.v = v
... 
>>> d = D(1)
>>> d.v
1
如果您担心对
\uuuu init\uuuu
的多次调用,那么您可以选择使用装饰器还是元类

重写
\uuuuu new\uuuuuu
方法允许多个
\uuuuu init\uuuuuu
调用,因为如果返回的值是
\uuu new\uuuuu
类的实例,python总是调用该对象的
\uuuu init\uuuuu
方法

无论如何,我认为使用装饰器是最好的,因为它可能是更简单的解决方案

如果您想知道更多在python中创建单例的方法,请阅读下面的问题

顺便说一下,如果希望所有实例都具有相同的状态(而不是标识),那么您可能会对该模式感兴趣。
如果您不确定要选择哪一个,请参阅答案。

因为我们都忽略了您的问题,而是建议替代的单例实现,所以我将介绍我最喜欢的。它利用了这样一个事实,即python模块只加载一次,而不管您导入它多少次

它还基于python的座右铭“我们这里都是同意的成年人”,因为如果你真的想,你可以多次实例化它。。。但是你真的需要付出额外的努力去做错事

所以在mysingleton.py中:

class SingletonClass(object):
    def __init__(self):
        # There's absolutely nothing special about this class
        # Nothing to see here, move along
        pass

# Defying PEP8 by capitalizing name
# This is to point out that this instance is a Singleton
Singleton = SingletonClass()

# Make it a little bit harder to use this module the wrong way
del SingletonClass
然后像这样使用它:

from mysingleton import Singleton

# Use it!
我说你必须付出额外的努力去做错事。以下是如何创建singleton类的两个实例,使其不再是singleton:

another_instance = Singleton.__class__()
那么如何避免这个问题呢?我要引用医生的话:那就别那么做


注意:这是在作出以下评论后添加的

当我在做这件事的时候,这里有另一个单例变体,它将复杂代码的数量降至最低。它使用元类:

class SingletonMeta(type):
    # All singleton methods go in the metaclass
    def a_method(cls):
        return cls.attribute

    # Special methods work too!
    def __contains__(cls, item):
        return item in cls.a_list

class Singleton(object):
    __metaclass__ = SingletonMeta
    attribute = "All attributes are class attributes"

    # Just put initialization code directly into the class
    a_list = []
    for i in range(0, 100, 3):
        a_list.append(i)

print Singleton.a_method()
print 3 in Singleton
在python 3中,您将创建如下的单例实例:

class Singleton(metaclass=SingletonMeta):
    attribute = "One... two... five!"

现在这个有点不确定,因为singleton是一个类,您可以创建singleton的实例。理论上这是可以的,因为即使有实例,单例仍然是单例,但是您需要记住,
singleton()
不是单例--
singleton
是!它甚至可以满足您的需要,使singleton属性作为类属性随时可用于其实例。

您知道
\uuuuuu new\uuuu()
?您似乎在做一些扭曲,以便能够将此模式插入到
\uuuu init\uuuu()
。对我来说非常适合。。。你能展示一下你用来测试它的代码吗?我试过使用new,但我做不到,有太多的代码,我无法分享…你有没有机会将其子类化?我不太熟悉
\uu new\uuuuuuu
中的所有魔法以及如何有效地使用它,但我的印象是,这仍然会在同一个实例上多次调用
\uuuuu init\uuuu
(这是我认为OP试图避免的)Yes@mgilson您是对的。我经常使用这种方法,因为我不太关心多个init调用。我已经添加了一个关于为什么这个方法会进行多个init调用的简要说明。我喜欢这个。我唯一不喜欢的是,你真的有一个实例,你根本不能自定义实例的创建。e、 g.你不能做
Singleton('foo'、'bar'、'baz')
(除非你提供
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。创建单例的最简单方法是只实例化一次类!很好,真正的单身汉。奇怪的是,在删除后,它仍然可以使用另一个类(Singleton.\uuuu class\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuo)和在
SingletonClass
中定义的函数(“方法”),比如
def boo(self):print'boo!'
仍然适用于另一个类的实例。沿着这些思路,
b=Singleton.\uuuuu class\uuuuu()
也可以工作
isinstance(b,Singleton.\uuu class\uuuuu)
(显然?)给出
True
…(续
b=Singleton.\uu class\uuuuu()
):
b是Singleton
False
我会添加def getinstance(*args,**kwargs):如果cls不在实例中:instances[cls]=cls(*args,**kwargs),a和b为什么是一样的?它不会给你不同的单身实例吗?@codemuncher——哪个版本?在第一个版本中,您可以看到,在第一次调用时,它设置了
cls.\uu实例
,然后在后续调用中继续返回相同的
cls.\uu实例
。在第二个版本中,它在创建函数时创建单例,然后继续返回该值(除非您为
\u singleton
)传递不同的值)。第二个版本,对于我的下一个调用b=foo\u singleton\u factory(),它不会创建另一个对象吗,我很困惑。不,默认参数仅在创建函数时计算一次。它们不会在后续通话中重新评估。这是python中各种混乱的根源:-)。看看另一个例子,它会吸引人,但事实并非如此