Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extending base classes in Python

Tags:

python

I'm trying to extend some "base" classes in Python:

class xlist (list):
    def len(self):
        return len(self)

    def add(self, *args):
        self.extend(args)
        return None


class xint (int):
    def add(self, value):
        self += value
        return self


x = xlist([1,2,3])
print x.len()   ## >>> 3 ok
print x         ## >>> [1,2,3] ok
x.add (4, 5, 6)
print x         ## >>> [1,2,3,4,5,6] ok

x = xint(10)
print x         ## >>> 10 ok
x.add (2)
print x         ## >>> 10  # Not ok (#1)

print type(x)         ## >>> <class '__main__.xint'> ok
x += 5
print type(x)         ## >>> <type 'int'>  # Not ok (#2)

It works fine in the list case because the append method modifies the object "in place", without returning it. But in the int case, the add method doesn't modify the value of the external x variable. I suppose that's fine in the sense that self is a local variable in the add method of the class, but this is preventing me from modifying the initial value assigned to the instance of the class.

Is it possible to extend a class this way or should I define a class property with the base type and map all the needed methods to this property?

like image 899
PabloG Avatar asked Aug 28 '08 22:08

PabloG


1 Answers

Your two xint examples don't work for two different reasons.

The first doesn't work because self += value is equivalent to self = self + value which just reassigns the local variable self to a different object (an integer) but doesn't change the original object. You can't really get this

>>> x = xint(10)
>>> x.add(2)

to work with a subclass of int since integers are immutable.

To get the second one to work you can define an __add__ method, like so:

class xint(int):
    def __add__(self, value):
        return xint(int.__add__(self, value))

>>> x = xint(10)
>>> type(x)
<class '__main__.xint'>
>>> x += 3
>>> x
13
>>> type(x)
<class '__main__.xint'>
like image 119
dF. Avatar answered Oct 05 '22 03:10

dF.