new-style-classes mixin

Greg Chapman glc at well.com
Wed Aug 7 17:57:39 CEST 2002


On 6 Aug 2002 06:16:25 -0700, joost_jacob at hotmail.com (J.Jacob) wrote:

>Oh you are thinking about changing the class itself, thus changing all
>class instances.  My doMixin function only changes an object of <type
>"instance">, adding a class to its .__bases__.

Actually, your doMixin function does change the bases for all instances (I
believe that's probably why it is read-only in new-style classes).  For example
(using your definitions):

cc1 = CC()
cc2 = CC()
doMixin(cc2, BC)
print cc1.__class__.__bases__
print cc2.__class__.__bases__

results in:

(<class __main__.AC at 0x00767D70>, <class __main__.BC at 0x007696B8>)
(<class __main__.AC at 0x00767D70>, <class __main__.BC at 0x007696B8>)

so cc1's bases got changed even though doMixin was called on cc2.

Here's an example which creates a new (mix-in) class on the fly, and sets the
given instance's class to it:

def doMixinNew(targetInstance, extraClass, name=''):
    instanceClass = targetInstance.__class__
    if not name:
        name = instanceClass.__name__+'_'+extraClass.__name__
    newClass = type(name, (instanceClass, extraClass), {})
    targetInstance.__class__ = newClass

cc1 = C()
cc2 = C()
doMixinNew(cc2, B)
print cc1.__class__.__bases__
print cc2.__class__.__bases__

which results in:

(<class '__main__.A'>,)
(<class '__main__.C'>, <class '__main__.B'>)

Note: changing the class of a new-style instance like this may very well break
if either of the classes involved uses __slots__.  Also, if you intend on
calling doMixin new frequently with the same combination of classes, it might be
worthwhile to change it to use some sort of cache to save the newly created
combination classes (since creating a new type is a relatively expensive
operation).

---
Greg Chapman




More information about the Python-list mailing list