tags:

views:

273

answers:

3

I have a __new__ method as follows:

class MyClass(object):
   def __new__(cls, *args):
      new_args = []
      args.sort()
      prev = args.pop(0)
      while args:
         next = args.pop(0)
         if prev.compare(next):
            prev = prev.combine(next)
         else:
            new_args.append(prev)
            prev = next
         if some_check(prev):
            return SomeOtherClass()
      new_args.append(prev)
      return super(MyClass, cls).__new__(cls, new_args)

   def __init__(self, *args):
       ...

However, this fails with a deprecation warning:

DeprecationWarning: object.__new__() takes no parameters

SomeOtherClass can optionally get created as the args are processed, that's why they are being processed in __new__ and not in __init__

What is the best way to pass new_args to __init__?

Otherwise, I'll have to duplicate the processing of args in __init__ (without some_check)

A: 

Since you don't even necessarily create a MyClass object, why not just put new into a separate function new(*args) that returns a MyClass or SomeOtherClass object as necessary?

This will be a bit neater since you know that everywhere you put MyClass() you get a MyClass object back, and not potentially SomeOtherClass, which could be a bit confusing.

Daniel G
In my case this is by design as MyClass and SomeOtherClass are cooperative types, and can be treated interchangeably (common interface).
EoghanM
+1  A: 

Edit: Came up with a better solution - the following wasn't behaving consistently enough.


I've solved my own question by stumbling on some unexpectedly simple behaviour:

return cls(*new_args)

instead of

return super(MyClass, cls).__new__(cls, *new_args)

It doesn't go into an infinite recursion, as I expected, so long as new_args is not the same as the original args given to __new__.

EoghanM
+1  A: 

The solution I went with in the end was to modify the newly created object in the __new__ and remove the __init__ method altogether:

def __new__(cls, *args):
   ... # as above
   new_self = super(MyClass, cls).__new__(cls)
   new_self.args = new_args
   return new_self

#def __init__(self, *args):
#    self.args = args
EoghanM