Limits of Metaprogramming

castironpi castironpi at gmail.com
Thu Aug 7 17:29:13 EDT 2008


On Aug 7, 2:01 pm, Wilson <PaulAlexWil... at gmail.com> wrote:
> On Aug 6, 6:04 pm, castironpi <castiro... at gmail.com> wrote:
>
>
>
> > On Aug 6, 7:24 am, Wilson <PaulAlexWil... at gmail.com> wrote:
>
> > > On Aug 4, 9:23 pm, castironpi <castiro... at gmail.com> wrote:
>
> > > > On Aug 4, 1:57 pm, Wilson <PaulAlexWil... at gmail.com> wrote:
>
> > > > > On Aug 4, 6:49 pm, castironpi <castiro... at gmail.com> wrote:
>
> > > > > > Two, if all your methods will have uniform signatures and closures,
> > > > > > you can store class methods as only their co_code objects:
>
> > > > > > >>> C.g.im_func.func_code.co_code
>
> > > > > > 'd\x00\x00S'
>
> > > > > > And fabricate them dynamically into full live types as needed.
>
> > > > > Thanks for your comments and advice. This second option intrigues me;
> > > > > could you elaborate further, I don't follow you...
>
> > > > > Thanks Paul
>
> > > > Depending on the complexity of the functions, a code string could be
> > > > all you need to store to determine (redetermine) a function's
> > > > behavior.  For something moderately simple,
>
> > > > def trans1( self, prev, trans ):
> > > >         if prev== 0 and trans== 'a':
> > > >                 return 1
> > > >         if prev== 1 and trans== 'b':
> > > >                 return 0
> > > >         return prev
>
> > > > I found you need to store code.co_nlocals, code.co_code, and
> > > > code.co_consts, to distinguish from a blank stub.  With extra
> > > > variables, I needed code.co_names and code.co_varnames too.  To
> > > > recreate a code object completely, you need 12 variables (14 to
> > > > include closures), some of which are composite objects and would need
> > > > to be pickled to be stored.
>
> > > Still don't really understand this so I'm going to admit defeat.
> > > Thanks all for your advice... Very much appreciated!
>
> > I was describing an alternative to storing functions in a way that
> > wasn't in serial in plain text.  It was off-topic from state-machine
> > transitions.
>
> > Can you start with this?
>
> > # state, input, next state
> > transitions= [
> >   ( 0, 'a', 1 ),
> >   ( 1, 'a', 2 ),
> >   ( 2, 'a', 0 ),
> >   ( 0, 'b', 0 ),
> >   ( 1, 'b', 0 ),
> >   ( 2, 'b', 2 )
> > ]
>
> > What further?
>
> My problem relates to the states really. I'd like to import a file
> containing the state classes into a "state editor" that is just a
> class editor really. Then, at *runtime* I'd like to add and remove
> methods from this class and change its attributes (__dict__). I'd also
> like to be able to add and remove classes from the module. When done,
> I was hoping to do introspection upon which classes were associated
> with this module and write back the modified class definitions to the
> same module. Next time the module is imported, the changes would
> remain intact. Unfortunately, inspect.getsource() reads the original
> file and does not magically return source from the runtime objects.
>
> Hope that makes sense!
> Paul

I see.  You want:

import states

def funa( ):
  something( )

states.funa= funa

And have those changes appear in the actual text of 'states.py'.

Are you certain that classes are your best choice for representing
states?  I am interpreting that you want one class per state, and one
method per transition out of that state.  How close is that?

If you are seeking to generate a .py file from a data structure, why
not just edit the data structure directly?  If you do need a .py file,
can you just regenerate it?



More information about the Python-list mailing list