new-style-classes mixin

J.Jacob joost_jacob at hotmail.com
Thu Aug 8 13:29:14 CEST 2002


[Greg Chapman]
> Here's an example which creates a new (mix-in) class on the
> fly, and sets the given instance's class to it:
> <snip> your code </snip>

Thank you for your example!  Much better for new-style classes
since it does more closely what I intended to do.  I did not
know you could have more than 1 parameter with type(...), I did
not find it in the 2.2.1 docs I have (searched library index).
Where did you read about it?

But!

It throws a TypeError when adding an old style class to an
object of an old style class.  Maybe we have to do some trick
that 'declares' a new style class there?  Or use assigning to
.__bases__ in this case?

It throws a TypeError when adding a new style class to an
object of an old style class.  Probably has to do with the
problem above.  

Do you know a fix for this?  Otherwise I think I will just have
to give up on the mixin technique for a while until I understand
it all better and things get stable and fixed in a new Python
version.

I feel like doing something bad when using so much __xxx__ and
_xxx attributes.  Maybe Python needs an official builtin mixin
function to do things like they are supposed to be done.



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

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

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


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

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

class C(object):
    def mc(self):
        print 'c'
#
################################################################



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


# Your example works when adding a new style class to an object
# of a new style class:
cc1 = C()
cc2 = C()
print 'adding extraClass:%s to targetObj:%s of class:%s' % (B,
        cc2, cc2.__class__)
doMixinNew(cc2, B)
print 'cc1.__class__.__bases__:', cc1.__class__.__bases__
print 'cc2.__class__.__bases__:', cc2.__class__.__bases__
print

# Adding an old style class to an object of an old style class
# crashes:
cc1 = CC()
cc2 = CC()
print 'adding extraClass:%s to targetObj:%s of class:%s' % (BC,
        cc2, cc2.__class__)
doMixinNew(cc2, BC)
print 'cc1.__class__.__bases__:', cc1.__class__.__bases__
print 'cc2.__class__.__bases__:', cc2.__class__.__bases__

"""    This produces:
adding extraClass:<class '__main__.B'> to targetObj:<__main__.C
object at 0x008A F870> of class:<class '__main__.C'>
newClass: <class '__main__.C_B'>
cc1.__class__.__bases__: (<type 'object'>,)
cc2.__class__.__bases__: (<class '__main__.C'>, <class
'__main__.B'>)

adding extraClass:__main__.BC to targetObj:<__main__.CC instance
at 0x00879BF8> of class:__main__.CC
Traceback (most recent call last):
  File "testmixin.py", line 63, in ?
    doMixinNew(cc2, BC)
  File "testmixin.py", line 41, in doMixinNew
    newClass = type(name, (instanceClass, extraClass), {})
TypeError: a new-style class can't have only classic bases
"""

# Adding a new style class to an object of an old style class
# crashes (comment out the other crashing code to get here):
cc1 = CC()
cc2 = CC()
print 'adding extraClass:%s to targetObj:%s of class:%s' % (B,
        cc2, cc2.__class__)
doMixinNew(cc2, B)
print 'cc1.__class__.__bases__:', cc1.__class__.__bases__
print 'cc2.__class__.__bases__:', cc2.__class__.__bases__

"""    This produces:
adding extraClass:<class '__main__.B'> to targetObj:<__main__.C
object at 0x008A C918> of class:<class '__main__.C'>
newClass: <class '__main__.C_B'>
cc1.__class__.__bases__: (<type 'object'>,)
cc2.__class__.__bases__: (<class '__main__.C'>, <class
'__main__.B'>)

adding extraClass:<class '__main__.B'> to targetObj:<__main__.CC
instance at 0x0 0879BF8> of class:__main__.CC
newClass: <class '__main__.CC_B'>
Traceback (most recent call last):
  File "testmixin.py", line 91, in ?
    doMixinNew(cc2, B)
  File "testmixin.py", line 43, in doMixinNew
    targetInstance.__class__ = newClass
TypeError: __class__ must be set to a class
"""
------------- end file testmixin.py  ---------------------------



More information about the Python-list mailing list