Dynamic variable creation from string

88888 Dihedral dihedral88888 at googlemail.com
Mon Dec 12 07:49:10 EST 2011


On Monday, December 12, 2011 3:11:18 PM UTC+8, alex23 wrote:
> On Dec 8, 3:09 am, Massi <mass... at msn.com> wrote:
> > in my script I have a dictionary whose items are couples in the form
> > (string, integer values), say
> >
> > D = {'a':1, 'b':2, 'c':3}
> >
> > This dictionary is passed to a function as a parameter, e.g. :
> >
> > def Sum(D) :
> >     return D['a']+D['b']+D['c']
> >
> > Is there a way to create three variables dynamically inside Sum in
> > order to re write the function like this?
> >
> > def Sum(D) :
> >     # Here some magic to create a,b,c from D
> >     return a+b+c
> 
> Okay, here's a possible solution that doesn't rely on exec, but does
> use the third-party module byteplay (which I believe limits it to
> Python 2.5-2.7) and tries to retain as much as possible your syntax
> (with some slight adjustments):
> 
>     from byteplay import Code, opmap
> 
>     class VariableInjector(dict):
>         def transmute(self, opcode, arg):
>             if (opcode == opmap['LOAD_GLOBAL']) and (arg in self):
>                 self._transmuted.append(arg)
>                 return opmap['LOAD_FAST'], arg
>             return opcode, arg

> 
>         def make_locals(self, args):
>             locals = []
>             for arg in args:
>                 locals.append((opmap['LOAD_CONST'], self[arg]))
>                 locals.append((opmap['STORE_FAST'], arg))
>             return locals
> 
>         def bind_to(self, function):
>             function.ofunc_code = function.func_code
>             def _(*args, **kwargs):
>                 self._transmuted = []
>                 code = Code.from_code(function.ofunc_code)
>                 code.code = [self.transmute(op, arg) for op, arg in
> code.code]
>                 code.code = self.make_locals(self._transmuted) +
> code.code
>                 function.func_code = code.to_code()
>                 return function(*args, **kwargs)
>             return _
> 
> For your example, you'd use it like this:
> 
>     >>> def sum():
>     ...     return a + b + c
>     ...
>     >>> def product():
>     ...     return a * b * c
>     ...
>     >>> data = VariableInjector(a=1,b=2,c=3)
>     >>> sum = data.bind_to(sum)
>     >>> product = data.bind_to(product)
>     >>> sum()
>     6
>     >>> product()
>     6
>     >>> data
>     {'a': 1, 'c': 3, 'b': 2}
>     >>> data['a'] = 100
>     >>> sum()
>     105
>     >>> product()
>     600
> 
> I'm not sure how rigorous this would be in real use but it's passed
> the few quick toy cases I've tried it out on.
> 
> Any thanks should go to Michael Foord, as this borrows heavily from
> his self-less metaclass example:
> http://www.voidspace.org.uk/python/articles/metaclasses.shtml

This is the way to write an assembler or 
to roll out a script language to be included in an app
by users. 




More information about the Python-list mailing list