Mix-In Class Methods At Run-Time

digitalorganics at gmail.com digitalorganics at gmail.com
Sun Jun 25 23:26:10 CEST 2006


Okay, while I'd still like to know the answer(s) to my earlier
question(s), I've mostly solved my problem thanks to bearophile and my
own learning. An example:

class Cat(object):
    def __init__(self):
        self.love = 0
    def meow(self):
        print "meow"
class Dog(object):
    def bark(self):
        print "bark"
class Bat(object):
    def scream(self):
        print "scream"
def Mixin(object, *classes):
    NewClass = type('Mixin', (object.__class__,) + classes, {})
    newobj = NewClass()
    newobj.__dict__.update(object.__dict__)
    return newobj
mycat = Cat()
mycat.love = 4
mycat = Mixin(mycat, Dog, Bat)
print mycat.__dict__, mycat.__class__, mycat.__class__.__bases__
print dir(mycat)

Two additional questions though: 1) is there a way for a function to
get a reference to its caller automatically (as in, without the caller
having to pass it in)? and 2) what's the reason to use newstyle classes
versus the old? In order to create the dynamic class "NewClass" in the
code above I called type() but that requires at least one new style
class as a base. Thus, I had to have at least one of my animals inherit
from "object" and this seemed a nuisance since I don't at this point
know what the benefit of "newstyle" classes is. I was going to just use
the new module and classobj() but I read somewhere that that was
unadvisable and newstyle classes should be used in new code. ...

Thank you.

Cheers,
DigiO

digitalorganics at gmail.com wrote:
> This looks excellent bearophile, but I'm having trouble understanding
> some things. Perhaps you can help wipe clean my ignorance. Firstly, I
> thought __classes__ was a read-only attribute? Secondly, what is a
> "dictproxy object" and why won't the following code work:
>
> class Cat:
>     def meow(self):
>         print "meow"
> def MixIn(object, *classes):
>     temp = type('ClassPie', (object.__class__,) + classes, {})
>     temp.__dict__.update([object.__dict__])
> NewClass = MixIn(Cat(), C, D)
> test = NewClass()
>
> __dict__, to my understanding, is suppose to be a dictionary, but
> Python keeps telling me it's a 'dictproxy' object and that it has no
> attribute 'update'. Why is this?
>
> Thanks.
>
>
> bearophileHUGS at lycos.com wrote:
> > I think it's possible, most of such kind of things are possible with
> > Python.
> > I'm not an expert yet in such kind of things, so this can be a starting
> > point for you (note the shadowing of m2, the class docstrings, etc).
> > Other people can give you something better or more correct.
> >
> > class A:
> >     def m1(self): return "m1"
> >     def m2(self): return "m2"
> >
> > class B:
> >     def m3(self): return "m3"
> >
> > class P:
> >     def m2(self): return "m2b"
> >     def m4(self): return"m4"
> >
> > def mixin(object, *classes):
> >     class NewClass(object.__class__):
> >         pass
> >     for C in classes:
> >         NewClass.__dict__.update(C.__dict__)
> >     object.__class__ = NewClass
> >
> > foo = P()
> > print "Before:"
> > print "foo.__class__.__dict__.keys():", foo.__class__.__dict__.keys()
> > print "P.__dict__.keys():", P.__dict__.keys()
> > print "foo.m2():", foo.m2()
> > print "foo.m4():", foo.m4(), "\n"
> >
> > mixin(foo, A, B)
> >
> > print "After:"
> > print "foo.__class__.__dict__.keys():", foo.__class__.__dict__.keys()
> > print "P.__dict__.keys():", P.__dict__.keys()
> > print "foo.m1():", foo.m1()
> > print "foo.m2():", foo.m2()
> > print "foo.m3():", foo.m3()
> > print "foo.m4():", foo.m4()
> > 
> > Bye,
> > bearophile




More information about the Python-list mailing list