Chapter 5: Function Basic

In programming world, reuse is just as important as in real life. One way to do this is using functions.

Functions are chunks of code that can be reused.

??+++Use your editor instead of Python console when working on more than a few lines of code, make it a file name: file.py. +++??

5.1 Function definition

Functions are defined using the def keyword. After this keyword comes an identifier name for the function, followed by a pair of parentheses which may enclose some names of variables, they are called parameters of the function. The final colon ends the line. Next follows the block of statements that are part of this function.

Compound statements Pattern:

  • A header line which begins with a keyword and ends with a colon.
  • A body consisting of one or more Python statements, each indented the same amount from the header line. (4 spaces is the Python standard)

We’ve already seen the if statement which follows this pattern.

The syntax for a function definition is:


def function_name(parameter1, parameter2...):
  code    # standard indentation of four spaces
  code
  ...
  • Function names follow the rules for legal identifiers that were given previously.

  • The parameters specify things, if any, that the user need to provide in order to use the new function. The parameter list may be empty, or it may contain any number of parameters separated by commas.

  • the parentheses are required no matter there is parameter or not.

Simple function with no input parameters Ex. 5.1-1 say_hello.py

Ex. say_hello.py
>>>def say_hello():
       print ("Hello! How are you?") 
>>>
>>>say_hello()  # Run the function by calling it's name
Hello! How are you?

Function with a string as input parameter Ex. 5.1-2 say_hello2.py

# ex. 5.1-2 say_hello2.py
>>> def say_hello2(name):
      print ("Hello! " + name)
>>>
>>> say_hello2('Emily')
Hello! Emily
>>> # run the function by calling it's name and provide input argument 'Emily' to parameter (name)

Functions can return values

Programmers typically want functions to return some value, so the code that called the function can work with. To support returning a value from a function, Python provides the return statement.

  • Any value provided to the return statement is passed back to your calling code.
  • All Python functions return the value None unless there is an explicit return statement with a value other than None.

  • Return statement will be the last line of a function. The function terminates at the return statement. You should not have any statements in a function after the return statement.

Ex. 5.1-3 add.py

# ex. 5.1-3 add.py
>>>def add_numbers(x, y):
       return x + y     # return statement at the end
>>>add_numbers(3,5)
8

5.2 Function call

Actually we've been using this already. When we need to run the code in a function, we need to do function call. Function call contains the name of the function to be executed followed by a list of values, called arguments, which are assigned to the parameters in the function definition.

Using the specified function name anywhere in your program and any number of times, you can run that block of code. We have already used many built-in functions such as print(),type(), len() and int(), range().

Two ways below show how to pass values to the parameters of function Ex. 5.1-3 add_numbers(x,y)

  • (1) directly pass literal values
    >>>add_number(4,8)
    12
    
  • (2) pass variables as arguments
    >>>m=3
    >>>n=6
    >>>add_number(m,n)
    9
    

The first time we call the function add_number(x.y), we directly supply the numbers as arguments.

In the second case, we call the function with variables as arguments. add_number(m,n)causes the value of argument m to be assigned to parameter x and the value of argument n to be assigned to parameter y. The add_number(x,y) function works the same way in both cases.

Function add_number(x,y)will return the value of x+y.

Another example to show passing values to parameters. Ex. 5.2-1 hello_again.py

>>>def hello(fname,lname):
       return 'Hello %s %s!' % (fname,lname)
>>>
>>>print hello('Jims', 'Bond')
Hello Jims Bond!   
>>>
>>>firstN= 'Donald'
>>>lastN = 'Duck'
>>>print hello (firstN, lastN)
Hello Donald Duck!

Functions can Call Other Functions

Let's write a function called square simply computes the square of a given number. Then another function called sum_of_squares makes use of square to compute the sum of three numbers that have been squared.

Ex. 5.2-2 squareNsum.py

# ex. 5.2-2 squareNsum.py
>>>def square(x):
     y = x * x
     return y
>>>    
>>>def sum_of_squares(x, y, z):
     a = square(x)
     b = square(y)
     c = square(z)
     return a + b + c
>>>    
>>>a = 5
>>>b = 2
>>>c = 10
>>>result = sum_of_squares(a, b, c)
>>>print(result)
129

composition is to build functions by using other functions. We will get to more of this later.

Check your understanding with more examples:

Ex. 5.2-3 addThem.py What will the following function return?

# ex. addThem.py
def addThem(x, y, z):
    print(x + y + z)

(A) Nothing (or None) (B) The value of x + y + z (C) The string 'x + y + z' Correct answer is A, this function returns None, eventhough this function will print out the result of x+y+z.

Ex. 5.2-4 compare_numbers.py

Ex. 5.2-4 compare_numbers.py
def compare_numbers(a, b):
    if a > b:
        print(a, 'is bigger')
    elif a == b:
        print(a, 'is equal to', b)
    else:
        print(b, 'is bigger')

Ex. 5.2-5 square_cube.py

# ex. 5-6 square_cube.py
>>>def get_square_cube(number):
        square = number**2
        cube = number**3
        return 'square',square, 'cube', cube
>>>answer = get_square_cube(3)
>>>print (answer)
('square', 9, 'cube', 27 )

5.3 Exercises on Function

Ex. 5.3-1 bigger.py Compare two numbers

# ex. 5.4-1 bigger.py
def bigger(x, y):
    if x > y:
        return x, 'is bigger'
    elif x == y:
        return 'The numbers are equal'
    else:
        return y, 'is bigger'
print(bigger(2, 3))
...#run
3 is bigger

Ex. 5.3-2 min_of_three.py Find the smallest of three numbers:

# ex. 5.4-2 min_of_three.py
def min_of_three(a,b,c):
    min=0
    if a<b:
        if a<c:
            min=a
        else:
            min=c
    else:
        if b<c:
            min=b
        else:
            min=c
    return min, 'is the smallest'

print(min_of_three(10, 12, 3))
...#run
3 is the smallest

Ex. 5.3-3 even_odd.py Check if a number is odd or even

# even_odd.py
def even_odd(n):
    if n%2==0 :
        return '%d is even'% n
    else:
        return '%d is odd'% n
print(even_odd(12))
print(even_odd(15))
...#run
12 is even     
15 is odd

Ex. 5.3-4 area_of_circle.py Calculate the area of a circle which is centered at point(x1,y1), and point(x2,y2) is on its edge.

# ex. 5.3-4 area_of_circle.py

# distance between two points
def distance(x1, y1, x2, y2):
    dx = x2 - x1
    dy = y2 - y1
    dsquared = dx**2 + dy**2
    result = dsquared**0.5  
    return result

# the area of circle with radius r
def area(r):
    b = 3.14159 * r**2
    return b

# area of circle centered at(xc,yc), has a point (xp,yp) on edge
def area2(xc, yc, xp, yp):
    radius = distance(xc, yc, xp, yp)
    result = area(radius)
    return result

print(area2(0,0,2,2))
...#run
25.1327

Function area2() in the above program can be easily rewrite as area3.py

Ex. 5.3-5 area3.py

# ex. 5.4-5 area3.py
def area3(xc, yc, xp, yp):
    return area(distance(xc, yc, xp, yp))
print (area3(0,0,2,2)
...#run
25.1327

More example to understand Boolean Functions Ex. 5.3-6 divisible.py, check to see if one number is divisible by another number.

# divisible.py
def isDivisible(x, y):
    if x % y == 0:
        result = True
    else:
        result = False
    return result

print(isDivisible(10, 5))
...#run
True
>>>

We can make the function more concise by taking advantage of the fact that the condition of the if statement is itself a Boolean expression. We can return it directly, avoiding the if statement altogether:

Ex.5.3-7 better_divisible.py

# better_divisible.py
def isDivisible2(x, y):
    return x % y == 0

isDivisible2(20,5)
...#run
True

Notice in the below file how descriptive the code is when we move the testing details into a Boolean function. Try it with a few other actual parameters to see what is printed. . Ex. 5.3-8 test_divisible.py, add testing to isDivisible2( )

# test_divisible.py
def isDivisible2(x, y):
    return x % y == 0
def test_divisible(i,j):
    if isDivisible2(10, 5):
        print("That works")
    else:
        print("Those values are no good")

test_devisible(10,2)
...#run
That works
test_devisible(10,3)
...#run
Those values are no good

Palindrome A fun program to look at: We take that text and reverse it. If the original text and reversed text are equal, then the text is a palindrome.(Kayak, Mom, noon)

Ex. 5.3-9 palindrome.py

def reverse(text):
    return text[::-1]


def is_palindrome(text):
    return text.lower() == reverse(text.lower())


something = input("Enter text: ")
if is_palindrome(something):
    print("Yes, it is a palindrome")
else:
    print("No, it is not a palindrome")
...#run
Enter text: Kayak
Yes, it is palindrome

5.4 Pro Topic

Parameters and Arguments

Parameters

Parameters are part of a function definition. Parameters define what types of arguments a function can accept.

We've been using positional-or-keyword parameters, they are normal parameters in a function definition, with or without default values. Other kinds of parameters we will not go into details here.

Arguments

Arguments are part of a function call. They are the values actually passed to a function when calling it.

There are four different kinds of arguments: (We often use the fist two in this book:)

  • positional: Arguments without a name.
  • keyword: Arguments with a name.

  • Other arguments are packed positional, packed keyword.

Assign arguments values to parameters: Look at this example:

Ex. 5.4-1 area.py

>>>def area(pi, radius):
    return pi*radius**2
>>> 
>>>print(area(3.14, 5))  # call area( )
78.5
>>>
>>> m,n = 3.14, 5
>>> print(area(m,n))    # call area( )

Positional assignment: (We have been using all along) In the above function call area(3.14, 5), the two numbers, 3.14 is assigned to pi, and 5 is assigned to radius based on their position. Same reason for the last two lines, m (value 3.14) is assigned to parameter pi, and n(value 5) is assigned to parameter radius.

Keyword assignment: In Python, we can also use the name (keyword) instead of the position to specify the arguments to the function, position ordering no longer applies. Ex. 5.4-2 call_area.py

# ex. 5.3-2 call_area.py
>>> # continue with the above function area(pi, radius)
>>> # keyword assignment
>>>print(area(pi=3.14, radius= 5))
78.5
>>>print(area(radius= 5, pi=3.14))
78.5       # using keyword assignment, any ordering is acceptable

Keyword assignment has two advantages

  • One, no need to worry about the order of the arguments.
  • Two, we can give values to only those parameters to which we want to, provided that the other parameters have default argument values,see below:

Specifying Default Values for Arguments: First, look at the following example: Ex. 5.4-3 minus.py

# ex. 5.3-3 minus.py
>>>def minus(x,y):   
       return x - y
>>>
>>>minus()    

TypeError: minus() missing 2 required 
positional arguments: 'x' and 'y'

To avoid this, we can assign default argument value to any parameter of a function. Then the default value can be automatically used if the code calling the function fails to supply an alternate value or the user just don't want to provide those values every time he calls the function (like in area(), pi = 3.14159).

We can specify default argument values for function parameters this way: after the parameter name append the assignment operator (=) followed by the default value.

Assign default argument value: Ex. 5.4-4 minusAgain.py

# ex.  minusAgain.py
>>>def minusAgain(x=0,y=0):    # set default values for x,y
       return x - y
>>>
>>>minusAgain()       # missing arguments value for x,y
0                # no error, x,y have default value 0
>>>
>>>minusAgain(10,2)
8
>>>m,n = 12,3
>>>minusAgain(m, n)
9

Let's redo area() Ex. 5.4-5 area2.py

>>>def area(radius, pi=3.14159):
    return pi*radius**2
>>> 
>>>print(area(5))
78.53975

Notes CAUTION

  • def func1(a, b=5) is valid,
  • def func2(a=5, b) is not valid.

Only those parameters which are at the end of the parameter list can be given default argument values i.e. you cannot have a parameter with a default argument value preceding a parameter without a default argument value in the function's parameter list. This is because the values are assigned to the parameters by position. When you make function call and provide only one value, like func1(10), the first parameter a will get this value, b is 5 by default. In the second example, func2(a=5,b), if we call func2(10), a will get two values, 5 and 10, and b gets no value.

==?=Pro Topic

5.5 Variable Scope

Functions bring up the topic of scope. A variable that is accessible by any function or code in the program has global scope. A variable that is only accessible inside a function has local scope.

Local variables

An variable assigned for the first time within a function creates a local variable. It is called local because this variable only exists inside the function and you cannot use it outside. Function parameters are also local and act like local variables.

Ex. 5.5-1 local.py

def var_demo(n):
    var1_in = 2
    var2_in = 4
    return (var1_in + var2_in) * n
...
>>>print ( var_demo(3) )  # call var_demo, returns (2+4)*3
18
>>>print (var1_in)
...
NameError: name 'var1_in' is not defined
...
>>>print (n)
...
NameError: name 'n' is not defined
...

In var_demo(n), there are 3 local variables: n, var1_in, var2_in.

The local variables only exist while the function is being executed, they disappear after the function returns. Local variable are usable only within the function they belong to, they are not visible outside the function.

Global variables

Global variables are variables declared outside any function, they have global scope, they are visible anywhere within the program, inside or outside of functions.

Let's define a variable before we create our function, see if we can use it inside the function.

Ex. 5.5-2 global.py

# ex. global.py
var_out = 10
def var_demo2():
    var1_in = 2
    var2_in = 4
    return var1_in * var2_in * var_out
...
>>>print ( var_demo2() ) 
80  
>>>print (var_out)
10
>>>print (var1_in)
...
NameError: name 'var1_in' is not defined

Let's look at another example to understand the scope of global and local variables:

Ex. 5.5-3 local_pi.py

# ex. local_pi.py   
def area(r,pi):
    '''return the area of a circle with radius r'''
    a = pi * r**2   
    return a

# calculate the area of a circle 

>>>print(area(5, 3.14))
78.5
>>>print (pi)
...
NameError: name 'pi' is not defined
>>>print (a)
NameError: name 'a' is not defined

In the file, local_pi.py, function area has 3 local variables: r,pi,a. Because pi is local variable, it's not visible outside of function area.

Next we will define pi as global variable,

Ex. 5.5-4 globle_pi.py

# global_pi.py

pi = 3.14    # global pi
def area2(r):
    '''return the area of a circle with radius r'''
    a = pi * r**2   
    return a

# calculate the area of a circle 
>>>print(area2(5))
78.5
>>>print (pi)
3.14

Here in area2, pi is not a local variable, it's declared outside any function, it's global.

Let's spend a minute look at an important rule about how variables are looked up in Python. First, Python looks at the variables that are defined as local variables in the function. We call this the local scope. If the variable name is not found in the local scope, then Python looks at the global variables, or global scope. This is exactly the case illustrated in the code above. pi is not found locally in area2 but it does exist globally.

Using global variables has the potential for the programmer to get confused. A better way to write area function would be to pass pi as a parameter with default value 3.14.

Ex. 5.5-5 better_area.py

# ex. better_area.py   
def goodArea(r,pi=3.14):
    '''return the area of a circle with radius r'''
    a = pi * r**2   
    return a

# calculate the area of a circle 

>>>print(goodArea(5))
78.5

Note that it is legal for a function to access a global variable. However, this is considered bad form by nearly all programmers and should be avoided.

Check out this:

Ex. 5.5-6 badPower.py

# badPower.py
def badPower(x, p):
    power = p     # Watch out! local 'power'
    y = x ** power
    return y

power = 3         # Watch out! global 'power'

>>>result = badPower(10, 2)    
>>>print(result)
100

When a local variable has the same name as a global variable we say that the local shadows the global. A shadow means that the global variable cannot be accessed by Python because the local variable will be found first.

Here in badPower, local power shadows global power, so we get the square of 10 instead of the cube of 10. Isn't it confusing?!

The appropriate way to calculate the square of a number would be to pass power as a parameter. For practice, let's rewrite an example goodSquare to have a second parameter called power.

Ex. 5.5-7 goodSquare.py

# goodSquare.py
def goodSquare(x, power=2):   
    y = x ** power
    return y

>>>result =goodSquare(10)    
>>>print(result)
100

Everybody happy, right?

Note: Generally programmers would avoid using global variables because of the potential to confuse people. If you must use global variables, make sure they have unique names.

===

pro topic

5.6 Docstring

DocStrings( documentation strings) are an important tool that you should make use of since it helps to document the program better and makes it easier to understand.

A string on the first logical line of a function is the DocString for that function. Note that DocStrings also apply to modules and classes which we will learn about in later chapters. Amazingly, we can even get the DocString back from, say a function, when the program is actually running!

The convention followed for a DocString is a multi-line string where the first line starts with a capital letter and ends with a dot. Then the second line is blank followed by any detailed explanation starting from the third line. You are strongly advised to follow this convention for all your DocStrings for all your non-trivial functions.

Docstrings can be accessed from the interpreter and from Python programs using the "doc" attribute:

Ex. 5.6-1 docstring.py

# ex. docstring.py
def area(r):
"""This function returns the area of circle.
The radius is r, using formula: area= 3.14*r**2."""
return 3.14*r**2

print (area(5))
print (area._doc_)
...#run
78.5
This function returns the area of circle.
The radius is r, using formula: area= 3.14*r**2.

==================end

results matching ""

    No results matching ""