# Indexed variables

Magnus Lycka lycka at carmen.se
Tue Sep 27 09:17:31 CEST 2005

```python-novice at gmx.de wrote:
> Hello,
>
> being an almost complete Python AND programming neophyte I would like to ask
> the following - very elementary, as I might suspect - question:
>
> How do I do the following flawed things right:
>
>
> a1=a2=0
>
> def f(x):
>     if x == a1:
>         a1 = a1 + 1
>     elif x == a2:
>         a2 = a2 + 1

It seems you are a bit confused about objects and names now... See
http://www.fredosaurus.com/notes-cpp/arrayptr/60song.html
For a more helpful reference, see
http://effbot.org/zone/python-objects.htm
(You are comparing integers here, not some kind of variable
names that you can see in your code.)

I also suspect that you haven't quite understood how functions are
intended to work. They should really know as little as possible about
the code outside them.

> Now if I call f with f(a2) only a1, of course, is incremented because the
> if-clause does only check for the value of the input and the values of a1
> and a2 are identical.
>
> So how do I define the function such as to discrimate wheter I call it by
> f(a1) or f(a2) ?

Others have talked about mutable and immutable objects,
and object immutability is a very good thing. If you have
an immutable object a1 somewhere in your code (which has
now grown to a few hundred lines) and look at something
like...

...
a1 = 0
f(a1)
print a1
...

...you will know for sure than the result of the last line
is that "0" is printed. There is no way that the line f(a1)
can change a1, however the callable object f (function or
whatever) is written if this is Python.

This makes it easier to write and understand Python code.
Sure, f(a1) is bound to mean something important, otherwise
it wouldn't be therer, but you can follow how a1 changes
without looking at the definition of f right now. That might
sound moderately important, but it's really a big benefit.

I assume that a "real f" would do more than add 1, but
assuming that it does the same thing with whatever value
you pass in, as I suspect you intend, your best option
would be to make it return the intended result, and to
reassign your variable to that. I.e:

...
def f(x):
return x + 1
...
a1 = a2 = 0
a1 = f(a1)
print a1
a2 = f(a2)
...

In this case, even if the definition of f is hundreds of
lines away from the other three lines of code, you will
see at once that something happens with a1 between the
"a1 = 0" and "print a1". You'll understand that you need
to understand what "f" does to know the state of a1.

Assuming that you give your functions more intelligent
names than f (maybe add_one in this case) it will be
clearer what happens here.

Just as in mathematics, it's essential in programming to
"divide and conquer"--to split a problem into small parts,
understand and solve each individual part, and get the
whole system to work even if the whole system is too complex
to fully grasp at once.

For that reason, it's important to make the various parts
of a program as independent of each other as we can. A function
will enforce some kind of contract: It will only do it's work
right if it's supplied with reasonable input, but it should
know as little as possible about its surroundings. Ideally
it knows and assumes nothing about the code that calls it.

Another aid in making code clearer is object-oriented programming.
With o-o, you define new types (called classes) that capture
both the data structure and the program logic that belong
together. That way there will be no confusion regarding what
kind of object you pass to a function. The function is part of
the object itself. But that's another story...

```