Spring Semester 2007


Lecture Five: Methods (functions, procedures).
You've already seen several built-in functions in action. len(...), range(...), abs(...)

Python lets you create functions of your very own. Your functions work just like the ones that come standard with the language.

They go off and perform a task and then return control to your program. Let's work through some examples, to understand better.

Here's function that simply prints some text: How do you invoke this function?
def instructions():
    print """
      1. Remove the carafe, swing out the basket.
      2. Place a filter in basket, add ground coffee.
      3. Swing basket back, fill reservoir with water.
      4. Place carafe back in the machine, turn machine on.
      5. Water will heat up and flowthrough the coffee grounds
         and into the carafe. When no more coffee purs out it's done.
      6. Remove the carafe, pour into mug and enjoy. 
    """

From the command prompt it's something like this: What's the purpose of the parens?
>>> instructions()

      1. Remove the carafe, swing out the basket.
      2. Place a filter in basket, add ground coffee.
      3. Swing basket back, fill reservoir with water.
      4. Place carafe back in the machine, turn machine on.
      5. Water will heat up and flowthrough the coffee grounds
         and into the carafe. When no more coffee purs out it's done.
      6. Remove the carafe, pour into mug and enjoy. 
    

Here, no much. In general, though, it collects the parameters. Can you give an example in the current context?

Yes, here's a function that takes a list of instructions and prints them in order. Oh, this is more general. This can print any list.
coffee = [
    "Remove the carafe, swing out the basket.",
    "Place a filter in basket, add ground coffee.",
    "Swing basket back, fill reservoir with water.",
    "Place carafe back in the machine, turn machine on.",
    "Water will heat up and flowthrough the coffee grounds\n" +
    "\t   and into the carafe. When no more coffee purs out it's done.",
    "Remove the carafe, pour into mug and enjoy. " ]

def instructions(steps):
    for i in range(len(steps)):
        print "\t" + str(i + 1) + ". " + steps[i]

That's the whole point. I see now. I have another question.

What is it? What does it mean for a function to return a value?

Can you write abs(...)? What do you mean?

Give me an example of using abs(...) please. Something like this?
(3 + 5 + abs(3-5)) / 2

Yes, do you understand how abs(...) works? Yes, it's something that starts along the following lines:
def abs(value):
    if (value > 0):
        print value
    else:
        print (-1) * value

That's good, but what is wrong with this definition? It doesn't work in the expression I mentioned above.

Here's how this method needs to be written: What's the meaning of return?
def abs(value):
    if (value > 0):
        result = value
    else:
        result = (-1) * value
    return result

It passes back the value to the context in which the function was called. So in this expression
1 + abs(1-2)
the second term is replaced with (or by) what is returned?

That's correct. How about parameters and arguments?

What about them? Is there more than one way to pass information through them?

Yes. Here's an example: Interesting. In how many ways can you call this function?
def greeting(name = "dear friend", age = "how many years"):
    print "Happy birthday", name + "! I hear you are", age, "today?..."

Four ways, take a look: Ah, I see you have used positional parameters and positional arguments; positional parameters and keyword arguments; and default parameter values.
>>> greeting("John", 12)
Happy birthday John! I hear you are 12 today?...
>>> greeting("John")
Happy birthday John! I hear you are how many years today?...
>>> greeting(age = 8)
Happy birthday dear friend! I hear you are 8 today?...
>>> greeting()
Happy birthday dear friend! I hear you are how many years today?...
>>> 

Absolutely. Let's now talk about global variables and constants.

We need to talk about scope, then. Reading a global variable from inside a function is easy to understand; and so is shadowing a global variable from inside a function, I believe. Take a look at this example:
def moo():
    print x

def boo():
    x = 4
    print x

Notice that boo() is not changing a global variable. I understand. The following sequence of statements should make it even clearer:
>>> x = 10
>>> moo()
10
>>> boo()
4
>>> moo()
10
>>> 

How do you change the a global variable from inside a function, then? You just have to make sure Python understands you're referring to it.

Her's the modified code:
def moo():
    print x

def boo():
    global x
    x += 1
    print x
And here's how it runs:
>>> x = 10
>>> moo()
10
>>> boo()
11
>>> moo()
11
>>> x
11
>>> 

Let's wrap this up with a reference to a larger case study. Then state a couple of problems, for our practice.

The larger example is the Tic-Tac-Toe program. Here's the basic outline:
display the game instructions
determine who goes first
create an empty tic-tac-toe board
display the board
while nobody's won and there is no tie:
  if it's the human user's turn: 
    get the human move
    update the board with the move
  otherwise:
    calculate the computer's move
    update the board with the move
  display the board
  switch turns
congratulate the winner or declare a tie
    

It usually takes a bit of effort to get the design done. Here are the steps and the code that finish the program:

Here's the main method in the final program: It mimics the design perfectly.
def main():
    display_instruct()
    computer, human = pieces()
    turn = X
    board = new_board()
    display_board(board)

    while not winner(board):
        if turn == human:
            move = human_move(board, human)
            board[move] = human
        else:
            move = computer_move(board, computer, human)
            board[move] = computer
        display_board(board)
        turn = next_turn(turn)

    the_winner = winner(board)
    congrat_winner(the_winner, computer, human)


# start the program
main()
raw_input("\n\nPress the enter key to quit.")

In class we should discuss this a bit. Here's a brief description of each method, though:
display_instruct() Displays the game instructions.
ask_yes_no(question) Asks a yes or no question. Receives a question. Returns either a "y" or an "n".
ask_number(question, low, high) Asks for a number within a range. Receives a question, a low number and a high number. Returns a number in the range from low to high
pieces() Determines who goes first. Returns the computer's piece and human's piece.
new_board() Creates a new, empty game board. Returns a board.
display_board(board) Displays the board on the screen. Receives a board.
legal_moves(board) Creates a list of legal moves. Receives a board. Returns a list of legal moves.
winner(board) Determines the game winner. Receives a board. Returns a piece, "TIE", or None.
human_move(board, human)Gets the human's move from the player. Receives a board and the human's piece. Returns the human's move.
computer_move(board, computer, human)Calculates the computer's move. Receives a board, the computer piece, and the human piece. Returns the computer's move.
next_turn(turn)Switches turns based on the current turn. Receives a piece. Returns a piece.
congrat_winner(the_winner, computer, human) Congratulates the winner or declares a tie. Receives a winning piece, the computer's piece, and the human's piece.

We will also work on the following problems. Well, they don't look too bad!...

  1. Write a method that receives a string and plays Hangman with the user on that word.
  2. Write a method that receives a number between 1 and 100 and plays guess the number in 10 tries with the user.
  3. Write a method that receives a width and a height and returns a width times height matrix with random entries.
  4. Write a method that receives a string and returns the string with all the characters inside it shuffled up.

Solve the matrix problem in two ways: using nested lists and using dictionaries.


Updated by Adrian German for A202/A598