Assigning to __class__ attribute

kj no.email at please.post
Fri Dec 3 14:28:00 EST 2010



I have a couple of questions regarding assigning to an instance's
__class__ attribute.

The first is illustrated by the following interaction.  First I
define an empty class:

>>> class Spam(object): pass
... 

Now I define an instance of Spam and an instance of Spam's superclass:
>>> x = Spam()
>>> y = Spam.__mro__[1]() # (btw, is there a less uncouth way to do this???)
>>> [z.__class__.__name__ for z in x, y]
['Spam', 'object']

Now I define a second empty class:
>>> class Ham(object): pass
... 

Next, I attempt to assign the value Ham to x.__class__:

>>> x.__class__ = Ham
>>> [isinstance(x, z) for z in Spam, Ham]
[False, True]

This was the first surprise for me: assigning to the __class__
attribute not only isn't vetoed, but in fact changes the instances
class:

Oh-kaaaay...

First question: how kosher is this sort of class transmutation
through assignment to __class__?  I've never seen it done.  Is this
because it considered something to do only as a last resort, or is
it simply because the technique is not needed often, but it is
otherwise perfectly ok?

The second, and much bigger, surprise comes when I attempt to do
the same class-switching with y:

>>> y.__class__ = Ham
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __class__ assignment: only for heap types

(If you recall, y's class is object, the superclass of x.) Apparently
Spam is a "heap type" (whatever that is) but its superclass, object,
isn't.  This definitely rattles my notions of inheritance: since
the definition of Spam was empty, I didn't expect it to have any
significant properties that are not already present in its superclass.
What's going on here? Is this a bug, or a feature? I can see no
logical justification for allowing such class switching for only
some class and not others.

One last question:  as the questions above make clear, I have a
colossal muddle inside my head regarding Python's model of classes
and inheritance.  This is not for lack of trying to understand it,
but, rather, for exactly the opposite reason: in my zeal to gain
the fullest understanding of this topic, I think I have read too
much that is incorrect, or obsolete, or incomplete...

What is the most complete, definitive, excruciatingly detailed
exposition of Python's class and inheritance model?  I'm expressly
avoiding Google to answer this question, and instead asking it
here, because I suspect that there's some connection between my
state of utter confusion on this topic and the ease with which the
complete/definitive/highest-quality information can get lost among
a huge number of Google hits to popular-but-only-partially-correct
sources of information.  (In fact, I *may* have already read the
source I'm seeking, but subsequent readings of incorrect stuff may
have overwritten the correct information in my brain.)

TIA!

~kj




More information about the Python-list mailing list