[Tutor] generate a list/dict with a dynamic name..

Steven D'Aprano steve at pearwood.info
Sun Sep 27 19:40:31 CEST 2015


On Sun, Sep 27, 2015 at 12:38:05PM -0400, bruce wrote:
> Hi.
> 
> I can do a basic
>  a=[]
> to generate a simple list..
> 
> i can do a a="aa"+bb"
> 
> how can i do a
>  a=[]
> 
> where a would have the value of "aabb"
> 
> in other words, generate a list/dict with a dynamically generated name

You don't. That is a mistake. How would you use it? Suppose you could 
wave a magic wand and create such a variable:

    make_variable("aabb", 23)  # this doesn't actually work
    print aabb  # prints 23

But what is the point of doing that? Since you already know the variable 
name, just do it the good old fashioned way:

    aabb = 23
    print 23

"Ah," you say, "but what if I don't know what the name is until the 
program actually runs?"

    name = random.choice(['fred', 'barney', 'wilma', 'betty'])
    make_variable(name, 23)
    print ... # err, what the hell do I put here???


You can see the problem. `print name` doesn't work, since that will 
print the name itself (say, 'fred'). Working with dynamically generated 
names is just a nightmare. You **really** don't want to do there.

But... if you insist, and really want to shoot yourself in the foot... 
Python does give you the magic wand to do it. (But please don't.)

In fact, two magic wands. Here's the first, using eval and exec:

py> name = "fred"
py> exec("%s = 23" % name)
py> eval(name)
23


But don't do that:

(1) It's confusing to anyone who has to understand your code.
(2) It's really hard to debug when something goes wrong.
(3) It's slow. About 10 times slower than regular Python code.
(4) It may be a security risk.

If the code you exec() or eval() ever comes from an untrusted users 
(say, in a web application), you have just opened a serious back door 
into your computer.

Here's another way:

py> name = "fred"
py> globals()[name] = 42
py> print globals()[name]
42

That's a bit better, but still, don't do it.

However, it does give us a clue how to do this safely. Instead of using 
a global variable, we keep track of our "dynamic variables" in their own 
custom namespace. (A namespace is just a fancy word for an isolated 
collection of named things, i.e. variables.)

py> ns = {}
py> name = 'wilma'
py> ns[name] = 999
py> ns[name] += 1
py> print ns['wilma']
1000

By doing it this way, you can still dynamically generate your names, but 
keep them isolated from the rest of the program. And you can easily 
print out all your "variables" to see what's going on:

py> print ns
{'wilma': 1000}

It's just an ordinary dict.


-- 
Steve


More information about the Tutor mailing list