[Tutor] Functions ! [argument passing / local scope]

Danny Yoo dyoo@hkn.eecs.berkeley.edu
Tue, 28 Aug 2001 21:28:54 -0700 (PDT)


On Tue, 28 Aug 2001, Dutch wrote:

> I have a question about functions.  I hope I can ask this clearly (and
> get a clear answer too!)

We'll try.  *grin* However, remember that you can always stop us when we
start babbling; this is certainly not a "final answer" situation...

[As a warning, some of the below is a simplification, and ignores some
details.  But why complicate matters?  *grin*]



> I dont understand the variables "c_temp" or "f_temp" since they are not
> used anywhere else.
> 
> 1.
> I am -guessing- that the part of the program that calls on the
> function is sending a variable to be processed in the function and it
> is getting dumped in c_temp or f_temp. If thats the case, they why is
> it that the original variable is not used, in this case "temp"?

Yes, the "caller" is sending off a single value off to the temperature
conversion functions.  What's important to realize is that, as far as the
conversion function is concerned, this value could have come from
anywhere.  I'd better clarify what that means:

For example, we can just "plug it in" and pass values directly to a
function:

###
print "Fahrenheit 451 is actually"
print fahrenheit_to_celsius(451), "in the celsius scale."
###

So we don't need to always pass a variable to a function.  What happens is
that fahrenheit_to_celsius() will do the calculation, and, isolated within
that function, f_temp will equal 451.

In short: we're not passing "names" to functions, but their "values".


When our program does this:

###
print "Celsius:",fahrenheit_to_celsius(temp)
###

Python will first grab the value of "temp", and once it has that value,
Python will pass that value off to fahrenheit_to_celsius().


Here's another example:

###
>>> def square(thing):
...     return thing * thing
...
>>> some_number = 42
>>> square(some_number * some_number)
3111696
>>> def quadrify(thing):
...     return(square(thing) * square(thing))
...
>>> quadrify(some_number)
3111696
###

See if it the above makes any sense; it touches some of the questions
you're asking.





> 2.
> I'm guessing here too that many parts of a program with all their
> different variables can call the funtion so no one absolute vaiable
> can be used so this "dummy" (c_temp or f_temp) is used and I must
> therefore be careful not to use the same label (variable) anywhere
> else in my program.

Actually, it's ok to use the name "c_temp" or "f_temp" in other places in
your program.  Let's take a closer look at your program for a sec:

###
def celsius_to_fahrenheit(c_temp):
    return 9.0/5.0*c_temp+32

def fahrenheit_to_celsius(f_temp):
    return (f_temp - 32.0)*5.0/9.0
###


It turns out that we could have written the two functions above as:

###
def celsius_to_fahrenheit(temperature):
    return 9.0/5.0*temperature+32

def fahrenheit_to_celsius(temperature):
    return (temperature - 32.0)*5.0/9.0
###

which could be paraphrased in English as "To celsius_to_fahrenheit() some
'temperature' that we're given, here's what we do..." and "To
fahrenheit_to_celsius() some 'temperature' that we're given, here's what
we do..."

In both functions, the name "temperature" is a _placeholder_ for whatever
value we give to the functions when we do some calculations.  In technical
terms, we'd say that "temperature" is "local" to the function.

If we have a variable named "temperature" outside these functions, we can
still relax because the "temperature" inside is not the same thing as the
"temperature" outside.


Better give an example:

###
>>> temperature = "HOT!"
>>>
>>> def describe(temperature):
...     temperature = temperature*3
...     print "Wow, the temperature is", temperature
...
>>> describe(temperature)
Wow, the temperature is HOT!HOT!HOT!
>>> temperature
'HOT!'
###

This "local"ity is usually a good thing because it allows us to draw
"boxes" around each function: we can think that each function works in
isolation of the others, so a messup in one function stays isolated in
that function.



To get functions to communicate to the "outside world", we can use the
"return" keyword.  Looking at one of the functions again:

###
def fahrenheit_to_celsius(temperature):
    return (temperature - 32.0)*5.0/9.0
###

we can see that the only thing coming out --- being "returned" --- from
the function is the result of that particular calculation.

There are ways of breaking down the doors: we can explicitly say that a
variable is "global", but let's avoid that topic for today.  *grin*




> Im trying to follow the program (reading it) and understand what is
> happening.  It just wasnt clear where this 2 new lables came from and
> how the program "knows" what is to be used there.

It is positional: the first thing we pass to the function will be tied to
the first name in the argument list.  I'm not sure if you've encountered
functions that take in more than one thing, so here's an example of such a
beast:

###
>>> def makeFriends(friend1, friend2):
...     return friend1 + " and " + friend2
...
>>> makeFriends("bill", "ted")
'bill and ted'
>>> makeFriends("ted", "bill")
'ted and bill'
###

We usually try to keep the number of arguments that a function takes in
down: most of the functions in Python take in one argument to make it hard
to accidently reverse the order.


If any of this doesn't make sense, please feel free to holler.  *grin*