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
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

```