__init__ vs __new__

Neil Cerutti horpner at yahoo.com
Thu Jan 11 10:33:51 EST 2007


On 2007-01-11, Daniel Klein <danielkleinad at gmail.com> wrote:
> I've have a program that is using both of the methods below (in
> different classes of course) for initializing the class. The
> example below shows a class with the 2 methods with one
> commented out.
>
> class JsubroutineParameters(list):
>     "Represents a list of arguments for external subroutine calls."
>     # We only need to override methods which add objects to the list.
>
>     def __init__(self, alist = []):
>         for objekt in alist: _validateParameter(objekt)
>         self.extend(alist)
>
>     #def __new__(cls, alist = []):
>     #    for objekt in alist: _validateParameter(objekt)
>     #    return list.__new__(cls, alist)
>
> I don't really notice any behavioral difference. Is there in
> fact any difference in using one over the other? Performance?
> Side effects? ???
>
> I am using Python version 2.5.

The second version doesn't work the way you might be assuming.

Guido's paper says that mutable builtins like list have a dummy
__new__ static method. So 'return list.__new__(cls, alist)' does
nothing. It seems to work because the base class __init__
performs the initialization (assuming your __init__ above is
commented out). You can see this by providing a dummy __init__.

class Example(list):
  def __new__(cls, alist):
    return list.__new__(cls, alist)
  def __init__(self, alist):
    pass

>>> a = Example(range(5))
>>> a
[]

There is no need to use __new__ for mutable builtin types. Since
all you want from this construction is a side-effect, you can
nevertheless use it in this case.

Your __init__ should call the base-class __init__.

It's usually a bad idea to provide mutable types as default
arguments. Since you aren't modifying alist in __init__ you can
get away with it here, but getting in the habit of using the
below idiom might save you from a "gotcha" someday.

class JsubroutineParameters(list):
  def __init__(self, alist=None):
    if alist is None:
      alist = []
    for objekt in alist: _validateParameter(objekt)
    list.__init__(self, alist)

You will no longer need to call append.

-- 
Neil Cerutti



More information about the Python-list mailing list