Indexed variables

P

python-novice

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


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

Thank you very much,


Peter
 
R

Rocco Moretti

So how do I define the function such as to discrimate wheter I call it by
f(a1) or f(a2) ?

I don't want to sound rude, but I think you'll be better served by
telling us why you would want to do such a thing - ten to one someone
can suggest a better way to acomplish you end goal, rather than
discriminating on which variable is passed to a function.
 
T

Tom Anderson

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
 
M

Magnus Lycka

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,264
Messages
2,571,323
Members
48,006
Latest member
TerranceCo

Latest Threads

Top