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
Python singleton / object instantiation
提问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 = 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(又名单身),但这与您要问的问题不同;-)。
回答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):
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 = blah
and 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 如何处理名称的信息。