Changing an object's class

Gerald Klix Gerald.Klix at klix.ch
Mon May 26 10:35:15 EDT 2003


Perhaps a small code snippet from 2.3a2 pickle module may give you some 
hint:
     def _instantiate(self, klass, k):
         args = tuple(self.stack[k+1:])
         del self.stack[k:]
         instantiated = 0
         if (not args and
                 type(klass) is ClassType and
                 not hasattr(klass, "__getinitargs__")):
             try:
                 value = _EmptyClass()
                 value.__class__ = klass
                 instantiated = 1
             except RuntimeError:
                 # In restricted execution, assignment to inst.__class__ is
                 # prohibited
                 pass
         if not instantiated:
             try:
                 value = klass(*args)
             except TypeError, err:
                 raise TypeError, "in constructor for %s: %s" % (
                     klass.__name__, str(err)), sys.exc_info()[2]
         self.append(value)

I would say: You are in good (or bad) company with your solution.


HTH,
Gerald


marshall wrote:
> I am building a simple GUI and I want to determine the layout of
> objects at runtime.  So I have stored the objects as a dictionary of
> elements each of which is a dictionary of attributes including the
> type.  Each type is a class.  I could query the type on load and
> create each instance and load its attributes. But instead I used an
> empty class and then changed it based on the type. [I'm sure there is
> a comp sci name for this like meta-generator-abstract-whatnot - I call
> it a Doppelganger.]
> 
> class cDoppel:
>     def __init__(self,kw):
>         self.__dict__ = kw
>         self.__class__ = eval(kw['class'])
> 
> class cHalfBee:
>     pass
> 
> class cPoofta:
>     pass
> 
> class cContainer:
>     def __init__(self,elements):
>         for element in elements.items():
>             name, attributes = element
>             self.__dict__[name] = cDoppel(attributes)
> 
> #Test
> elements = {'Eric':{'class':'cHalfBee','attribA':(1,2),'attribB':25},'Bruce':{'class':'cPoofta','ears':2}}
> bag = cContainer(elements)
> print 'Bag has',dir(bag)
> print 'Eric has',dir(bag.Eric)
> print 'Eric is a ' + str(bag.Eric)
> 
> Output:
> Bag has ['Bruce', 'Eric', '__doc__', '__init__', '__module__']
> Eric has ['__doc__', '__module__', 'attribA', 'attribB', 'class']
> Eric is a <__main__.cHalfBee instance at 0x00C58BF0>
> 
> I like the results and might use this technique elsewhere.
> 
> Questions:
> Is this naughty or nice?  Why?
> Google shows some old, olympian discussion of locking down __class__
> but I did not see a resolution of it.  Will this be a mortal or a
> venal sin?
> 
> Thanks,
> Marshall





More information about the Python-list mailing list