Subclassing Python Tuples with Multiple __init__ Arguments

The following code works:

class Foo(tuple): def __init__(self, b): super(Foo, self).__init__(tuple(b)) if __name__ == '__main__': print Foo([3, 4]) $ python play.py play.py:4: DeprecationWarning: object.__init__() takes no parameters super(Foo, self).__init__(tuple(b)) (3, 4) 

But not the following:

 class Foo(tuple): def __init__(self, a, b): super(Foo, self).__init__(tuple(b)) if __name__ == '__main__': print Foo(None, [3, 4]) $ python play.py Traceback (most recent call last): File "play.py", line 7, in <module> print Foo(None, [3, 4]) TypeError: tuple() takes at most 1 argument (2 given) 

Why?

+44
python inheritance tuples subclass
Oct. 14 '09 at 10:10
source share
2 answers

Since tuples are immutable, you should override __new__ :

python docs

object.__new__(cls[, ...])

Called to create a new instance of class cls . __new__() is a static method (special case, so you do not need to declare it as such), which takes a class whose instance was as the first argument. the remaining arguments are those that passed to the expression of the constructor of the object (class call). The return value of __new__() should be a new instance of the object (usually this is an instance of cls ).

Typical implementations create a new instance of the class by calling the __new__() superclass method using super(currentclass, cls).__new__(cls[, ...]) with the appropriate arguments and then modifying the newly created if necessary before returning it.

If __new__() returns an instance of cls , then new instances of __init__() will be called as __init__(self[, ...]) , where self is the new instance and the rest of the arguments are the same as those passed before __new__() .

If __new__() does not return an instance of cls , then the new instance __init__() method will not be called.

__new__() is primarily intended to provide subclasses of immutable types (such as int , str or tuple ) for setting up instance creation. It is also commonly overridden in custom metaclasses in order to customize class creation.

+58
Oct 14 '09 at 10:24
source share

To assign a value to a tuple, you need to override the __new__ method:

 class Foo(tuple): def __new__ (cls, a, b): return super(Foo, cls).__new__(cls, tuple(b)) 

Arguments are apparently ignored by an implementation like tuple __init__ , but if you need to make some init files, you can do it like this:

 class Foo(tuple): def __new__ (cls, a, b): return super(Foo, cls).__new__(cls, tuple(b)) def __init__(self, a, b): self.a=a self.b=b if __name__ == '__main__': foo = Foo(None, [3, 4]) print foo print foo.a print foo.b 
+41
Oct 26
source share



All Articles