type(d) != type(d.copy()) when type(d).issubclass(dict)

John O'Hagan research at johnohagan.com
Sat Dec 25 21:40:16 EST 2010


On Sat, 25 Dec 2010, Steven D'Aprano wrote:
> On Sat, 25 Dec 2010 15:58:35 +0000, Duncan Booth wrote:
> > kj <no.email at please.post> wrote:
> >> Watch this:
> >>>>> class neodict(dict): pass
> >> 
> >> ...
> >> 
> >>>>> d = neodict()
> >>>>> type(d)
> >>
> >><class '__main__.neodict'>
> >>
> >>>>> type(d.copy())
> >>
> >><type 'dict'>
> >>
> >> Bug?  Feature?  Genius beyond the grasp of schlubs like me?
> > 
> > Feature.
> 
> I'd say it is neither, and call it a bloody nuisance that nevertheless
> has some justification.
> 
> > In (almost?) all cases any objects constructed by a subclass of a
> > builtin class will be of the original builtin class. So, for example,
> > subclass a string and concatenating your subclassed objects still
> > produces a string.
> 
> Yes, and the consequence is that any serious subclass must overload every
> method which returns a new instance, otherwise your new subclass doesn't
> "stick" -- you find it being replaced by the builtin as soon as you start
> doing something useful with it.
> 
> This is especially a nuisance for subclasses of (say) float, where you
> end up writing heaps of boilerplate like this:
> 
> class MyFloat(float):
>     def __add__(self, other):
>         return self.__class__(super(MyFloat, self).__add__(other))
>     # and the same for __mul__, __sub__, __rsub__, __pow__, ...
[...]

I've occasionally wished I could just:

import builtin_subclass_fixer

class MyList(list):
	def __init__(self):
		builtin_subclass_fixer.fix(self)
		...
	...
	
to automatically ensure that new objects returned by MyList methods are of the 
same class without my having to identify and override every such method.

IMO one of the benefits of subclassing is that you can just "bolt on" 
additional behaviour without having to know all the inner workings of the 
superclass, a benefit that is somewhat defeated by this behaviour of builtins.

OTOH - not that I advocate nuisance as a deterrent - the nuisance factor of 
this has encouraged me to look harder for simpler solutions. Most of the time 
I've realised I didn't really need to subclass at all, and thus avoided "lazy 
subclassing".

John



More information about the Python-list mailing list