Python Deprecation Warnings with Monostate __new__ -- Can someone explain why?
Asked Answered
S

2

5

I have a basic Monostate with Python 2.6.

class Borg(object):
    __shared_state = {}
    def __new__(cls, *args, **kwargs):
        self = object.__new__(cls, *args, **kwargs)
        self.__dict__ = cls.__shared_state
        return self

    def __init__(self, *args, **kwargs):
        noSend = kwargs.get("noSend", False)
        reportLevel = kwargs.get("reportLevel", 30)
        reportMethods = kwargs.get("reportMethods", "BaseReport")
        contacts= kwargs.get("contacts", None)

a = Borg(contacts="Foo", noSend="Bar", )

Which happily gives me the following Deprecation warning..

untitled:4: DeprecationWarning: object.__new__() takes no parameters
  self = object.__new__(cls, *args, **kwargs)

After a bit of googling I find this is attached to Bug #1683368. What I can't figure out is what this means. It's complaining about the following line

self = object.__new__(cls, *args, **kwargs)

Which appears to be OK. Can someone explain in laymens terms why this is a problem. I understand that "this is inconsistent with other built-ins, like list" but I'm not sure I understand why. Would someone explain this show me the right way to do it?

Thanks

Sharecropper answered 19/10, 2009 at 19:4 Comment(0)
U
6

See python-singleton-object-instantiation, and note Alex Martelli's singleton example:

class Singleton(object):

    __instance = None

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

The __new__ deprecation question was answered by Guido:

The message means just what it says. :-) There's no point in calling object.__new__() with more than a class parameter, and any code that did so was just dumping those args into a black hole.

The only time when it makes sense for object.__new__() to ignore extra arguments is when it's not being overridden, but __init__ is being overridden -- then you have a completely default __new__ and the checking of constructor arguments is relegated to __init__.

The purpose of all this is to catch the error in a call like object(42) which (again) passes an argument that is not used. This is often a symptom of a bug in your program.

--Guido

Unrobe answered 19/10, 2009 at 19:22 Comment(2)
That's a singleton (aka highlander) is not a borg (monostate). I have been [schooled][1] on that already. I also have ready Guido's comments but as I said earlier if your init has the requirements of *args **kwargs then new would also require them? Right?? [1]: #1576180Sharecropper
Guido explicitly says that only init is required to check constructor arguments.Unrobe
C
1

The warning comes from the fact that __new__() can HAVE args, but since they're ignored everywhere, passing args (other than cls) to it causes the warning. It's not actually (currently) an error to pass the extra args, but they have no effect.

In py3k it will become an error to pass the args.

Crossman answered 19/10, 2009 at 19:12 Comment(2)
I'm failing to see how they are ignored? Take out *args and **kwargs from new and it'll bomb because they are needed by init which is expecting them. You last statement is the one I'm trying to prevent :-) I want it to work in 3k.Sharecropper
I can't argue with the language designers. If they say "new doesn't take any arguments", I make it take no arguments. __init__ and __new__ function similarly, perhaps your use case should be using init instead of new.Crossman

© 2022 - 2024 — McMap. All rights reserved.