Hacking with __new__

Chris Mellon arkanes at gmail.com
Tue Jul 24 21:39:21 CEST 2007


On 7/24/07, Sandra-24 <sandravandale at yahoo.com> wrote:
> On Jul 24, 5:20 am, Bruno Desthuilliers <bruno.
> 42.desthuilli... at wtf.websiteburo.oops.com> wrote:
> > IIRC, __new__ is supposed to return the newly created object - which you
> > are not doing here.
> >
> > class Bar(Foo):
> >      def __new__(cls, a, b, c, *args):
> >          print 'Bar.__new__', len(args)
> >          if not args:
> >              cls = Zoo
> >          obj = super(Bar, cls).__new__(cls, a, b, c, *args)
> >          if not args:
> >              obj.__init__(a, b, c, 7)
> >          return obj
>
> Thanks guys, but you are right Bruno, you have to return the newly
> created object or you get:
>
> >>> b = Bar(1,2,3)
> Bar.__new__ 0
> Foo.__new__ 3
> Zoo.__init__ 4
> Foo.__init__ 3
> >>> b is None
> True
>
> However, if you return the object you get:
>
> >>> b = Bar(1, 2, 3)
> Bar.__new__ 0
> Foo.__new__ 3
> Zoo.__init__ 4
> Foo.__init__ 3
> Traceback (most recent call last):
>   File "<input>", line 1, in <module>
> TypeError: __init__() takes exactly 5 arguments (4 given)
>
> Which is the same blasted error, because it seems to want to call init
> on the returned object and it's calling it with 4 args :( Is there any
> way around that?
>

__init__ is going to be called with the arguments passed to __new__
and there doesn't seem to be any way to affect that. Your only option
to make it not happen is for Zoo not to be a subclass of Bar.

Possible workarounds:
Each subclass of Bar needs a corresponding __new__

Each subclass of Bar needs a cooperating __init__ that detects (via
optional arguments) if it's being called by Bar.__new__ or directly
and noops in the second case.



More information about the Python-list mailing list