On 12/3/10 1:28 PM, kj wrote:
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?
Last resort for very special purposes, and only extremely rarely in production.
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.
Feature. When you have C-implemented types, you cannot safely swap out their
instance's __class__. There are memory issues involved. Only subclasses of
object made by the class statement (or the equivalent type(...) call), i.e.
"heap types", permit this modification. object is a C-implemented type.
Importantly, as for most other C-implemented types, plain object instances have
no __dict__.
Types and classes were unified a long time ago in Python 2.2, but there are
still relevant distinctions between C-implemented types and Python-implemented
types.
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.)
http://www.python.org/download/releases/2.2.3/descrintro/
--
Robert Kern
"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
--
http://mail.python.org/mailman/listinfo/python-list