简体   繁体   English

Python单例/对象实例化

[英]Python singleton / object instantiation

I'm learning Python and i've been trying to implement a Singleton-type class as a test. 我正在学习Python,并且我一直在尝试将Singleton类型的类作为测试。 The code i have is as follows: 我的代码如下:

_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. 这部分工作,但self = __instance部分似乎失败了。 I've included some output from the interpretor to demonstrate (the code above is saved in singleton.py): 我已经包含了解释器的一些输出来演示(上面的代码保存在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. 干杯。

Assigning to an argument or any other local variable (barename) cannot ever, possibly have ANY effect outside the function; 分配给参数或任何其他局部变量(barename)不可能在函数外部产生任何影响; that applies to your self = whatever as 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(又名单身人士),但这与你所询问的问题不同;-)。

Bruce Eckel's code snippet from Design Pattern: I'm confused on how it works 来自Design Pattern的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>
'''

From Singleton Pattern (Python) : Singleton Pattern(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()

This is about the most basic Singleton you can make. 这是关于你可以做的最基本的单身人士。 It uses a class method to 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__方法

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. 首先,在调用__init__ ,已经创建了一个新对象,从而破坏了单例模式的目的。 Second, when you say self = __instance , that simply resets the local variable self; 其次,当你说self = __instance ,它只是重置局部变量self; this would be akin to saying 这就像说的那样

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 = blah and have it be meaningful in the way you want. 由于Python中的变量是按值而不是引用传递的,因此您不能说self = blah并且以您想要的方式使其有意义。 The above Singleton class is more what you want, unless you want to get fancy and look into overriding the __new__ operator. 上面的Singleton类更符合你的要求,除非你想得到花哨的东西并且考虑覆盖__new__运算符。

self = _instance

This wont do what you are expecting it to do. 这不会做你期望它做的事情。 Read about how Python treats names. 阅读Python如何处理名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM