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