Python 单例/对象实例化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1363839/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 22:03:47  来源:igfitidea点击:

Python singleton / object instantiation

pythonsingleton

提问by JonahSan

I'm learning Python and i've been trying to implement a Singleton-type class as a test. The code i have is as follows:

我正在学习 Python,我一直在尝试实现一个单例类型的类作为测试。我的代码如下:

_Singleton__instance = None

class Singleton:
    def __init__(self):
        global __instance
        if __instance == None:           
            self.name = "The one"
            __instance = self
        else:
            self = __instance

This works in part but the self = __instance part seems to be failing. I've included some output from the interpretor to demonstrate (the code above is saved in singleton.py):

这部分有效,但 self = __instance 部分似乎失败了。我已经包含了解释器的一些输出来演示(上面的代码保存在 singleton.py 中):

>>> import singleton
>>> x = singleton.Singleton()
>>> x.name
'The one'
>>> singleton._Singleton__instance.name
'The one'
>>> y = singleton.Singleton()
>>> y.name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Singleton instance has no attribute 'name'
>>> type(y)
<type 'instance'>
>>> dir(y)
['__doc__', '__init__', '__module__']

Is it possible to do what i'm trying? If not is there another way of doing this?

有可能做我正在尝试的事情吗?如果没有,还有另一种方法吗?

Any suggestions welcome.

欢迎任何建议。

Cheers.

干杯。

回答by Alex Martelli

Assigning to an argument or any other local variable (barename) cannot ever, possibly have ANY effect outside the function; that applies to your self = whateveras it would to ANY other assignment to a (barename) argument or other local variable.

分配给一个参数或任何其他局部变量(裸名)永远不可能在函数之外产生任何影响;这适用于您,self = whatever就像对(裸名)参数或其他局部变量的任何其他赋值一样。

Rather, override __new__:

相反,覆盖__new__

class Singleton(object):

    __instance = None

    def __new__(cls):
        if cls.__instance == None:
            cls.__instance = object.__new__(cls)
            cls.__instance.name = "The one"
        return cls.__instance

I've done other enhancements here, such as uprooting the global, the old-style class, etc.

我在这里做了其他增强,例如连根拔起全局、旧式类等。

MUCH better is to use Borg(aka monostate) instead of your chosen Highlander (aka singleton), but that's a different issue from the one you're asking about;-).

更好的是使用Borg(又名 monostate)而不是您选择的 Highlander(又名单身),但这与您要问的问题不同;-)。

回答by Dustin Getz

Bruce Eckel's code snippet from Design Pattern: I'm confused on how it works

布鲁斯·埃克尔 (Bruce Eckel) 的设计模式代码片段:我对它的工作原理感到困惑

class Borg:
  _shared_state = {}
  def __init__(self):
    self.__dict__ = self._shared_state

class MySingleton(Borg):
  def __init__(self, arg):
    Borg.__init__(self)
    self.val = arg
  def __str__(self): return self.val

x = MySingleton('sausage')
print x
y = MySingleton('eggs')
print y
z = MySingleton('spam')
print z
print x
print y
print ′x′
print ′y′
print ′z′
output = '''
sausage
eggs
spam
spam
spam
<__main__. MySingleton instance at 0079EF2C>
<__main__. MySingleton instance at 0079E10C>
<__main__. MySingleton instance at 00798F9C>
'''

回答by Corey D

From Singleton Pattern (Python):

单例模式(Python)

class Singleton(type):
    def __init__(self, name, bases, dict):
        super(Singleton, self).__init__(name, bases, dict)
        self.instance = None

    def __call__(self, *args, **kw):
        if self.instance is None:
            self.instance = super(Singleton, self).__call__(*args, **kw)

        return self.instance

class MyClass(object):
    __metaclass__ = Singleton

print MyClass()
print MyClass()

回答by Eli Courtwright

This is about the most basic Singleton you can make. It uses a class methodto check whether the singleton has been created and makes a new one if it hasn't. There are more advanced ways of going about this, such as overriding the __new__method.

这是关于您可以制作的最基本的单身人士。它使用一个类方法来检查是否已经创建了单例,如果没有,则创建一个新单例。有更高级的方法来解决这个问题,例如覆盖__new__method

class Singleton:
    instance = None

    @classmethod
    def get(cls):
        if cls.instance is None:
            cls.instance = cls()
        return cls.instance

    def __init__(self):
        self.x = 5       # or whatever you want to do

sing = Singleton.get()
print sing.x  # prints 5

As for why your code fails, there are several reasons. First, by the time __init__is called, a new object has already been created, defeating the purpose of the singleton pattern. Second, when you say self = __instance, that simply resets the local variable self; this would be akin to saying

至于为什么你的代码失败,有几个原因。首先,在__init__被调用时,已经创建了一个新对象,这违背了单例模式的目的。其次,当您说 时self = __instance,这只是重置局部变量 self;这类似于说

def f(x):
  x = 7    # changes the value of our local variable

y = 5
f(y)
print y   # this is still 5

Since variables in Python are passed by value and not reference, you can't say self = blahand have it be meaningful in the way you want. The above Singleton class is more what you want, unless you want to get fancy and look into overriding the __new__operator.

由于 Python 中的变量是按值传递而不是引用传递,因此您不能说它self = blah以您想要的方式有意义。上面的 Singleton 类更符合您的要求,除非您想看中并考虑覆盖__new__运算符。

回答by truppo

self = _instance

This wont do what you are expecting it to do. Read about how Python treats names.

这不会做你期望它做的事情。阅读有关 Python 如何处理名称的信息。