Indexed variables

Tom Anderson twic at urchin.earth.li
Thu Sep 22 19:15:11 CEST 2005


On Thu, 22 Sep 2005 python-novice at gmx.de wrote:

> How do I do the following flawed things right:

Well, that depends on what you mean by 'right'. I'm going to give you two 
solutions; one that answers your apparent question, and one that addresses 
what i suspect is your true question.

> a1=a2=0
>
> def f(x):
>    if x == a1:
>        a1 = a1 + 1
>    elif x == a2:
>        a2 = a2 + 1

The problem here is to do with how variables work. When you say f(a2), you 
don't mean "call f, and pass a2 as the parameter", you say "call f, and 
pass the value of a2 as the parameter". It's a bit like if you have a cat, 
and two tins of sardines; you might say you feed a tin of sardines to the 
cat, but really, you're feeding it the sardines that were in the tin - you 
have to take them out of it first. Accordingly, if the sardines are 
identical, the cat has no way of knowing which tin the sardines came out 
of. I guess you know this.

So, first solution. What you can do is, rather than sending a value into 
f, is send the name of the variable you want to operate on, say as a 
string:

a1 = a2 = 0

def f(name):
 	if (name == "a1"):
 		a1 = a1 + 1
 	elif (name == "a2"):
 		a2 = a2 + 1

You could even do this fully generically, using some magic:

a1 = a2 = 0

def f(name):
 	g = globals()
 	g[name] = g[name] + 1

I make absolutely no warranty that this will always do what you expect!

However, in my centuries of experience on programming newsgroups, if 
there's one thing that i've learned, it's that people who want to do this 
usually don't actually want to do this. They have some real need for 
storing a varying number of values under arbitrary names, and they think 
that the way to do this is by having a different variable for each. They 
are almost always wrong.

What they really want is the second solution: a collection object, like a 
list or dictionary:

a = {}
a[1] = 0
a[2] = 0

def f(number):
 	a[number] = a[number] + 1

This avoids mucking about with the variable namespace, which is usually a 
bad idea, and it means you have all the variables grouped together in one 
place, making it easy to look at them all together, or pass them to some 
other function, or whatever.

For extra style, try this:

a = {}

def f(number):
 	a[number] = a.get(number, 0)

That effectively automatically initialises every value stored in a to 
zero.

Hope this helps,
tom

-- 
The ``is'' keyword binds with the same precedence as ``.'', even when it's not actually there. -- Larry Wall, Apocalypse 2



More information about the Python-list mailing list