I've dome some reading on the difference between __new__ and __init__, and 
never really groked it. I just followed the advice that you should almost 
always use __init__.

I recently came across a task that required using __new__ and not __init__. I 
was a bit intimidated at first, but it was quick and easy. This simple 
programming exercise really cleared a lot of things up for me. 

Not to be immodest, but I think something like this ought to be the canonical 
example for explaining when/how to override __new__.

The task? I want to make a class that behaves exactly like a tuple, except 
changing the constructor argument signature and adding some extra methods. An 
example should clarify what I needed.

> x = ParetoTuple(1, 2, 0)
> x[1]
>> 2
> len(x)
>> 3
> 2 in x
>> True
> -1 in x
>> False
> x.dominates(ParetoTuple(1, 3, 0))
>> True
> x.equivalent(ParetoTuple(1, 2 + 1e-5, 0))
>> True

etc.

Since I want the constructor to take an (almost) arbitrary number of arguments, 
each of which will be elements of the resulting ParetoTuple, I need to override 
__new__. I don't need to overwrite __init__, because the tuple.__new__ will 
populate it's data when the arguments are properly formatted. 

Also, since the world of Pareto comparisons makes sense only with 2 or more 
goals, I want my specialized constructor to take at least 2 arguments in a 
natural way.

Here is the code

class ParetoTuple(tuple) :
    def __new__ (cls, obj1, obj2, *rest):
        return super(ParetoTuple, cls).__new__(cls,  (obj1, obj2) + rest)
     # nothing special about the dominates, equivalents methods...
     # no __init__ needed

I understand some people argue in favor of using a factory pattern for this 
sort of situation, but I disagree. I think the cognitive overhead of factories 
requires a more complicated task than re-signaturing the constructor method.

At any rate, hope it helps others like it helped me.
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to