Assigning to .__class__

J.Jacob joost_jacob at hotmail.com
Sat Aug 10 17:58:48 CEST 2002


Assigning to .__class__ is a trick to change the type of an
instance.  This can be useful for mixin techniques.  

I have been trying to define a function called 'doMixin' that
adds functionality to an object.  I now have a doMixin function
that is satisfactory but not in every circumstance, and there are
still some questions.  The doMixin function in the file
mixintest.py below works if the object is an instance of a new
style class.  It also works if the object is an instance of an
old style class and you are adding an old style class.  It breaks
when adding a new style class to an old style class object, this
is because the NewClass definition in function doMixin will be of
type <type 'type'> and not of <type 'class'>.

The Library Reference (python version 2.2.1) has:
"""
2.2.10 Special Attributes 
The implementation adds a few special read-only attributes to
several object types, where they are relevant: 
<snip>
__class__ 
The class to which a class instance belongs
"""

In the new Python Cookbook I see other people also assigning to
__class__ (recipes 5.13, 15.10, maybe more, I own the book only
since today) so the 'read-only' in the Library Reference quoted
above suprised me.

Questions:
- abandon assigning to .__class__? 
- Can you give a definition for doMixin that works for all four
  cases?


    Running mixintest.py:

D:\src>python mixintest.py
result: (<class '__main__.C'>, <class '__main__.B'>)
result: (<class '__main__.C'>, <class __main__.BC at 0x00868AA0>)
result: (<class __main__.CC at 0x00869120>, <class __main__.BC at
0x00868AA0>)
Traceback (most recent call last):
  File "mixintest.py", line 51, in ?
    testmixin(CC, B)    # adding a new style class
  File "mixintest.py", line 42, in testmixin
    doMixin(obj, extraClass)
  File "mixintest.py", line 37, in doMixin
    obj.__class__ = NewClass
TypeError: __class__ must be set to a class


<leading-underscore-as-warning-signal-meaning-stay-out-'ly-yrs>


---------------------  file mixintest.py  ----------------------
################################################################
# A couple of classic classes
#
class AC:
    def ma(self):
        print 'ma'

class BC:
    def mb(self):
        print 'mb'

class CC(AC):
    pass
#
################################################################


################################################################
# A couple of new-style classes
#
class A(object):
    def ma(self):
        print 'ma'

class B(object):
    def mb(self):
        print 'mb'

class C(object, A):
    pass
#
################################################################


def doMixin(obj, extraClass):
    class NewClass(obj.__class__, extraClass): pass
    obj.__class__ = NewClass


def testmixin(targetClass, extraClass):
    obj = targetClass()
    doMixin(obj, extraClass)
    print 'result:', obj.__class__.__bases__


# object will be an instance of a new style class
testmixin(C, B)     # adding a new style class
testmixin(C, BC)    # adding an old style class
# object will be an instance of an old style class
testmixin(CC, BC)   # adding an old style class
testmixin(CC, B)    # adding a new style class

-----------------  end file mixintest.py  ----------------------



More information about the Python-list mailing list