Dynamic variable creation from string
88888 Dihedral
dihedral88888 at googlemail.com
Mon Dec 12 07:43:20 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
More information about the Python-list
mailing list