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

D

David Robinow

Watch this:

<type 'dict'>


Bug?  Feature?  Genius beyond the grasp of schlubs like me?
copy, here, is a dict method. It will create a dict.
If you really need it, you could try this:

import copy
class neodict(dict):
def copy(self):
return copy.copy(self)

d = neodict()
print type(d)
dd = d.copy()
print type(dd)
 
S

Steven D'Aprano


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).
 
J

John O'Hagan

I'd say it is neither, and call it a bloody nuisance that nevertheless
has some justification.


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
 
K

kj

John O'Hagan said:
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.

I agree. I've read the old post/articles by GvR and other over
how great it will be now that one can subclass Python builtin types
like any other class (GvR even gives explicit examples of this
luscious possibility in his paper on type/class unification). But
now I'm discovering so many caveats, exceptions, and gotchas about
subclassing builtins that I have to conclude that this much celebrated
new capability is basically useless... Just like "readability
counts", it is also true that "conceptual clarity" counts, and
treating builtins as classes in Python is the most obfuscated design
I've ever seen.

UserDict, come back, all is forgotten!

~kj
 
K

kj

In said:
In (almost?) all cases any objects constructed by a subclass of a builtin
class will be of the original builtin class.


What I *really* would like to know is: how do *you* know this (and
the same question goes for the other responders who see this behavior
of dict as par for the course). Can you show me where it is in
the documentation? I'd really appreciate it. TIA!

~kj
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top