问题描述
几年前,我发现一个Python的单例模式的实现由: class Singleton(object):
Duncan Booth的Singleton类
多个对象变量指的是同一个对象
http://web.archive.org/web/20090619190842/http:/ /www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html#singleton-and-the-borg
_instance =无
def __new __(cls ,* args,** kwargs):
如果不是cls._instance:
cls._instance = super(Singleton,cls).__新__(
cls,* args,** kwargs)
return cls._instance
同样的方法也在问题
我通过子页面使用Singleton -classing:
class Settings(Singleton)
class Debug(Singleton)
最近我对程序进行了一些修改,并得到了这个警告:
code> /media/KINGSTON/Sumid/src/miscutil.py:39:DeprecationWarning:
object .__ new __()不需要参数
cls._instance = super(Singleton,cls).__ new__ (cls,* args,** kwargs)
我发现(由Guido)发送邮件至mail.python.org/pipermail/python-dev/2008-February/076854.html说这个参数根本就不用了。传递一个不需要的参数可能是一个bug的症状。
所以我决定清除参数:
class Singleton(object):
_instance = None
def __new __(cls):
如果不是cls._instance:
cls._instance = super(Singleton,cls).__ new __()
return cls._instance
导致以下异常:
追溯(最近的最后一次呼叫):
文件sumid.py ,第1168行,< module>
settings = Settings()
文件/media/KINGSTON/Sumid/src/miscutil.py,第45行,__new__
cls._instance = super(Singleton,cls).__ new__ ()
TypeError:object .__ new __():没有足够的参数
当我修改行到 cls._instance = super(Singleton,cls).__ new __(cls)
,我会得到:
追溯(最近的最后一次呼叫):
文件sumid.py,第1174行,< module>
debug = Debug(settings)
TypeError:__new __()只需要一个参数(2个给定)
Gimmel建议另一个: _instance = type .__ new __(cls)
。对我来说,它打破了继承:
追溯(最近的最后一次呼叫):
文件sumid.py < module>中的行1168
settings = Settings()
文件/media/KINGSTON/Sumid/src/miscutil.py,第40行,__new__
_instance = type .__ new __(cls)
TypeError:type .__ new __(Settings):设置不是类型为
的子类型
相同的还有Menno Smits。但我不明白建议。此外,我没有相关代码中的多重继承。
Few years ago I found an implementation of the Singleton pattern in Python by Duncan Booth:
class Singleton(object):
"""
Singleton class by Duncan Booth.
Multiple object variables refers to the same object.
http://web.archive.org/web/20090619190842/http://www.suttoncourtenay.org.uk/duncan/accu/pythonpatterns.html#singleton-and-the-borg
"""
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(
cls, *args, **kwargs)
return cls._instance
The same approach is also described in question "Is there a simple, elegant way to define Singletons in Python?"
I use the Singleton via sub-classing:class Settings(Singleton)
class Debug(Singleton)
Recently I made some changes to the program and got this warning:
/media/KINGSTON/Sumid/src/miscutil.py:39: DeprecationWarning:
object.__new__() takes no parameters
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
I found explanation (by Guido) about __new__
deprecation which says that the parameters are not used at all. Passing an argument which is not needed can be symptom of a bug.
So I decided to clear the parameters:
class Singleton(object):
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__()
return cls._instance
Which resulted in following exception:
Traceback (most recent call last):
File "sumid.py", line 1168, in <module>
settings = Settings()
File "/media/KINGSTON/Sumid/src/miscutil.py", line 45, in __new__
cls._instance = super(Singleton, cls).__new__()
TypeError: object.__new__(): not enough arguments
When I modify the line to cls._instance = super(Singleton, cls).__new__(cls)
, I'll get:
Traceback (most recent call last):
File "sumid.py", line 1174, in <module>
debug = Debug(settings)
TypeError: __new__() takes exactly 1 argument (2 given)
Gimmel suggest another solution: _instance = type.__new__(cls)
. For me it breaks the inheritance:
Traceback (most recent call last):
File "sumid.py", line 1168, in <module>
settings = Settings()
File "/media/KINGSTON/Sumid/src/miscutil.py", line 40, in __new__
_instance = type.__new__(cls)
TypeError: type.__new__(Settings): Settings is not a subtype of type
The same problem has also Menno Smits. But I don't understand the solution suggested. Moreover I have no multiple inheritance in relevant code.
I didn't try the another example in "Is there a simple, elegant way to define Singletons in Python?", but at a glance it probably will have the same problem.
I use the Singleton pattern in a program and I don't want to rewrite it completely just because one warning. Thus following answers wont help me:
- Singleton is wrong. Don't use the Singleton at all.
- Use Borg instead, it's more pythonic.
- Use module instead of a class.
To conclude I'll repeat the question:
How to adapt the Singleton pattern with consideration of the deprecation warning with the minimal impact to existing code?
Edit:Line cls._instance = object.__new__(cls)
raises the TypeError when the Child's init takes an argument:
class Child(Singleton):
def __init__(self,param=None):
print(param)
print("Doing another stuff.")
ch = Child("Some stuff")
You need to drop any additional arguments you are passing when you construct the object. Change the offending line to:
cls._instance = object.__new__(cls)
or
cls._instance = super(Singleton, cls).__new__(cls)
though I think you'll be fine with the first (diamond inheritance and singletons sound as though they shouldn't be mixed).
P.S. I did try this suggestion and it works for me so I don't know why it didn't work for you.
Edit in response to @dragonx's comment: As pointed out in the comments, object.__new__
will throw an exception if you pass on *args, **kwargs
so the super call to __new__
should not include any arguments apart from cls
. This wasn't the case when the original article was written. Also of course if you choose to base your singleton on some other type such as a tuple
you would then need to pass the appropriate arguments.
这篇关于如何适应Singleton模式? (弃用警告)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!