On Fri, 25 Mar 2011 13:29:20 +0100, Seldon wrote: > On 03/25/2011 12:05 AM, Steven D'Aprano wrote: >> On Thu, 24 Mar 2011 19:39:21 +0100, Seldon wrote: >> >>> Hi, I have a question about generating variable assignments >>> dynamically. >> [...] >>> Now, I would like to use data contained in this list to dynamically >>> generate assignments of the form "var1 = value1", ecc where var1 is an >>> identifier equal (as a string) to the 'var1' in the list. >> >> Why on earth would you want to do that? >> >> > Because I'm in this situation. My current code is of the form: > > var1 = func(arg=value1, *args) > .. > varn = func(arg=valuen, *args) > > where var1,..varn are variable names I know in advance and > value1,..valuen are objects known in advance, too; func is a long > invocation to a factory function. Each invocation differs only for the > value of the 'arg' argument, so I have a lot of boilerplate code I'd > prefer to get rid of (for readability reasons).
If you *truly* need all those variables, and can't re-design your code to be simpler and neater, then you're stuck with an uncomfortable choice between: (1) Tedious boilerplate (2) If using global variables, you can inject new variables into the global namespace using globals()[name] = value (3) If using local variables, and you trust the data (you better, you wrote it!), then you can't use locals() but you can use exec, at considerable cost of speed. (By my testing, a call to exec is about ten times slower than a direct execution of the same source code.) All three are bad code-smells. They tell me that you probably should re- think your algorithm to have less reliance on named variables created with a "long invocation to a factory function" -- particularly if they differ only by a single parameter. But, if you can't change your design, I'd prefer the tedious boilerplate of (1) over (3), and prefer (2) only if it involved multiple dozens of variables. For half a dozen, or even two dozen, I'd stick to the boilerplate. Yes, it sucks, but that's because the design sucks, and not every piece of code is destined to be a thing of beauty. The reason that I would prefer tedious boilerplate is twofold: - Although it's a code-smell, it's less of a smell than exec or the use of global variables. You read code more than you write it: I'd rather the pain of writing the boilerplate once, than the continual "Hmmm, what's this nonsense then?" of reading it over and over again. - If you ever change the design, say the variables no longer differ in just one argument to the factory function, but a variable number of them, it's probably easier to change the boilerplate than it is to change the other two solutions. They're relatively inflexible without a lot of work, so boilerplate, as ugly as it is, is probably the safer and more conservative (less "clever") solution. Hope this helps. -- Steven -- http://mail.python.org/mailman/listinfo/python-list