new-style-classes mixin
J.Jacob
joost_jacob at hotmail.com
Thu Aug 8 07:29:14 EDT 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