Re: Python 2.6 Deprecation Warnings with __new__ — Can someone explain why?

Carl Banks pavlovevidence at gmail.com
Fri Oct 23 06:05:38 CEST 2009


On Oct 22, 8:12 pm, rh0dium <steven.kl... at gmail.com> wrote:
> Hi all,
>
> 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", )

Before we get into object semantics, I'm not sure why you'd need to
override __new__ for Borg pattern, unless they're working around some
edge cases or something.
For that matter you shouldn't need args and kwargs either, you know
what the arguments to your function are.

This should suffice for you:

class Borg(object):
    __shared_state = {}
    def __init__(self, noSend=False,reportLevel=30,
                 reportMethods="BaseReport",
                 contacts=None):
        self.__dict__ = self.__shared_state
        self.noSend = noSend
        self.reportLevel = reportLevel
        self.reportMethods = reportMethods
        self.contacts = contacts

This (as well as your class) will update the shared state for all Borg
objects whenever you instantiate a new Borg object.  That might be
what you want, but be aware.


> 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 Guidos answer means. FWIW - It's
> complaining about the following line
>
> self = object.__new__(cls, *args, **kwargs)
>
> Which appears (to me) to be OK. Can someone explain in laymens terms
> why this is a problem.

I don't mean to be flippant, but the reason you're seeing this error
is because object.__new__() takes no parameters.

There's not much more to it than that.

I'll explain below.


> 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?

object.__new__(cls)


> I have read
> Guido's answer on this but I guess I just don't understand his
> reasoning.  In short Guido said the following:
>
>   "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."
>
> In my case the args that it dumps them into a black hold is simply not
> true.

Actually it is.


> I want an unknown set of args and kwargs to simply be forwarded
> onto init.  So what's the problem with this??

The problem is that __new__ doesn't forward the arguments to
__init__.  Look at what happens when you call this class:

class X(object):
    def __new__(cls,*args,**kwargs):
        return object.__new__(cls)
    def __init__(self,*args,**kwargs):
        print args, kwargs

X(1,2,q=3,g=4)


Note that *args and **kwargs are not passed to object.__new__, but
nevertheless __init__ is still called with them.

What's actually happens is that the type object's __call__ method
passes the same arguments to both __new__ and __init__.

The fact is, object.__new__ does nothing at all with the args and
kwargs arguments, it just ignores them.  So, when calling
object.__new__, don't pass them to it.


Carl Banks



More information about the Python-list mailing list