new-style-classes mixin
Greg Chapman
glc at well.com
Wed Aug 7 11:57:39 EDT 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