type(d) != type(d.copy()) when type(d).issubclass(dict)
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Sat Dec 25 17:41:49 EST 2010
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__, ...
> This is reasonable behaviour as for builtin classes performance is more
> important than fully implementing polymorphism. If you want to subclass
> a builtin class you need to be aware of this and override the behaviour
> where it matters.
Yes, but I think builtins could probably afford one extra identity check.
Something like this:
# Pseudocode
if type(self) is builtin type:
do exactly what is done now
else:
do something slower, but kinder for superclasses
For all I know, the slower branch might be something as simple as calling
the C equivalent of type(self)(arg).
--
Steven
More information about the Python-list
mailing list