dynamic assigments

Steven D'Aprano steve+comp.lang.python at pearwood.info
Fri Mar 25 18:57:32 EDT 2011


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



More information about the Python-list mailing list