Code design for a sub-class of built-ins

Bruno Desthuilliers onurb at xiludom.gro
Tue Jul 4 13:26:36 EDT 2006


Steven D'Aprano wrote:
> I'm having problems with sub-classes of built-in types.
> 
> Here is a contrived example of my subclass. It isn't supposed
> to be practical, useful code, but it illustrates my problem.
> 
> class MyStr(str):
>     """Just like ordinary strings, except it exhibits special behaviour
>     for one particular value.
>     """
>     magic = "surprise"

>     def __init__(self, value):
>         str.__init__(self, value)

You don't need to override __init__ here.


>     def __len__(self):
>         if self == self.magic:
>             print "Nobody expects the Spanish Inquisition!"
>         return str.__len__(self)
>     def upper(self):
>         if self == self.magic:
>             print "Nobody expects the Spanish Inquisition!"
>         return str.upper(self)
>     # and so on for every last string method...

My my my....

> 
> The obvious problem is, I have to create a custom method for every string
> method -- 

which makes subclassing almost useless - except to pass isinstance() tests.

> and if strings gain any new methods in some future version of
> Python, my subclass won't exhibit the correct behaviour.

You could replace subclassing by composition/delegation using the
__getattr__ hook, but this would break tests on type/class :(

Or you could keep subclassing and use the __getattribute__ hook, but
this is more tricky and IIRC may have negative impact on lookup perfs.

Or you could use a metaclass to decorate (appropriate) str methods with
a decorator doing the additional stuff.

choose your poison !-)

> Here's a slightly different example:
> 
> class MyInt(int):
>     """Like an int but with special behaviour."""
>     def __init__(self, value, extra):
>         int.__init__(self, value=None)
>         self.extra = extra

Won't work. You need to override the __new__ staticmethod. Look for
appropriate doc here:
http://www.python.org/download/releases/2.2.3/descrintro/#__new__
(FWIW, read the whole page)

(snip)

> Looks like my __init__ isn't even being called here. Why not, and how do I
> fix this?

cf above

> Is there a way to subclass built-in types without needing to write the
> same bit of code for each and every method? 

cf above

> Am I approaching this the wrong way? Is there a better design I could be
> using?

probably !-)

HTH
-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list