Class.__class__ magic trick help

Ian Kelly ian.g.kelly at gmail.com
Mon Aug 20 14:39:38 EDT 2012


On Mon, Aug 20, 2012 at 12:01 PM, Massimo Di Pierro
<massimo.dipierro at gmail.com> wrote:
> I discovered I can do this:
>
>     class A(object): pass
>     class B(object):
>         __class__ = A # <<<< magic
>
>     b = B()
>     isinstance(b,A) # returns True (as if B derived from A)
>     isinstance(b,B) # also returns True
>
> I have some reasons I may want to do this (I an object with same
> methods as a dict but it is not derived from dict and I want
> isinstance(x,dict)==True to use it in place of dict in some other
> code).
>
> What are the problems with the magic trick above? Why does it work?

Normally with __class__ assignment, you would assign to the __class__
attribute of the *instance*, not the class declaration.  This actually
changes the class of the object, and so isinstance(b, B) would no
longer return True.

I've never heard of assigning it in the class declaration, and as far
as I know, this behavior isn't documented anywhere.  I expect that
what's happening here is that Python is not actually updating the
class of the instance, but that A is merely assigned to the
"__class__" attribute in the class dict, and that isinstance is
somehow (perhaps accidentally) finding this.  So I think this is
probably a bug, and I would not rely on it to work correctly in all
cases.

In any event, the use case that you're looking for is usually
accomplished using abstract base classes.  Instead of "isinstance(x,
dict)", you should use "isinstance(x, collections.MutableMapping)",
and then inherit your class from or register it with the
MutableMapping ABC.



More information about the Python-list mailing list