如何适应Singleton模式? (弃用警告) [英] How to adapt the Singleton pattern? (Deprecation warning)

查看:206
本文介绍了如何适应Singleton模式? (弃用警告)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

几年前,我发现一个Python的单例模式的实现由 Duncan Booth

  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

同样的方法也在问题有没有一种简单,优雅的方式来定义Python中的单例?



我通过子页面使用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)

我发现 __新__ 的rel =noreferrer>说明(由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。但我不明白解决方案建议。此外,我没有相关代码中的多重继承。



我没有尝试另一个

我在程序中使用Singleton模式,我不想仅仅因为一个警告而完全重写它。因此,以下答案不会帮助我:




  • Singleton是错误的。不要使用Singleton。

  • 使用Borg,它更多的是pythonic。

  • 使用模块而不是一个类。



总而言之,我将重复一个问题:

如何适应单身人士弃用警告的模式,使用现有代码的最小影响



编辑:
Line cls._instance = object .__ new __(cls)当孩子的init引用参数时引发TypeError:

  class Child(Singleton):
def __init __(self,param = None):
print(param)
print (做另一个东西)

ch = Child(Some stuff)


解决方案

您需要删除构建对象时传递的任何其他参数。将违规行更改为:

  cls._instance = object .__ new __(cls)

  cls._instance = super Singleton,cls).__新__(cls)

虽然我认为你会罚款的第一(钻石遗产和单身人士的声音好像不应该混合)。



我没有尝试这个建议,它适用于我,所以我不知道为什么它不适合你。



编辑响应@ dragonx的评论:如意见中所指出的那样,如果您传递 * args,** kwargs

object .__ new __ 将抛出异常code>所以超级调用 __ new __ 不应该包含除 cls 之外的任何参数。原文写的不是这样的。当然,如果你选择把你的单身人数作为其他类型,比如一个 tuple ,那么你需要传递适当的参数。


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模式? (弃用警告)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆