1 / 50

CS 115 Lecture

Functions in Python allow us to write code once and use it in multiple places. Learn how to define functions, call functions, and use parameters and arguments.

aclaudia
Télécharger la présentation

CS 115 Lecture

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CS 115 Lecture Functions Taken from notes by Dr. Neil Moore

  2. The idea behind functions Sometimes we have to repeat the same combination of control structures and steps in several different places. • Functions let you write the code once • … And then use it in multiple places • It’s like defining a new verb in the language • We’ve already seen several built-in and library functions • print, input, range • math.sin, random.randrange • Constructors: Graphwin, Rectangle • Methods: setText, getMouse

  3. The idea behind functions • And we know how to call them: • If it doesn’t return a value: func(arguments) • If it does return a value: result = func(arguments) • We’ve even written one of our own! • def main(): defines a function named main

  4. Calling a function: syntax To call (“invoke”) a function, you write its name, followed by its arguments in parentheses. • The name of the function is an identifier • Same rules as for variable names • Letters, digits, underscore, cannot start with digit • The arguments are a list of expressions, separated by commas • Arguments are “inputs” that the calling statement sends to the function • Each function specifies how many arguments it takes • Some like random() take no arguments • But they still need parentheses!

  5. Calling a function: semantics When you call a function: • The interpreter pauses execution of the code that made the function call • But it remembers where it was • The interpreter runs the code of the called function • It makes the arguments available to the function • The function finishes or returns • The interpreter picks up where it left off • The value of the function call Is whatever value the function returned (or None if it does not explicitly return anything)

  6. Structured programming guarantees • When a subprogram (function) finishes, control returns to where the function was called from • A function should have ONE return statement as the last line of the function definition (One entrance, one exit guarantee) or NO return statement, in which case all the statements in the definition are executed, then control returns to where it was called from

  7. Defining a function • To define a function, you need to specify three things: • The name of the function • What parameters the function takes • With a name for each parameter • This is called the parameter list • What the function does when called • The code or body of the function • As usual, an indented block

  8. Defining functions def name (parameters): body • Defines a function called “name” • Goes at the top level of the file • Unindented (at left margin) • Not inside main or other functions! • Parameters are a comma-separated list of identifiers • The function receives one argument for each parameter it has

  9. Defining functions • When Python sees the definition, it does NOT run the body! • Instead it remembers it and remembers its name • The body runs when you call the function • That’s why we need main() at the end of our file • If you don’t call a function, it will not run! • It does NOT run just because it is defined in the file • Something to check for when debugging

  10. A simple function definition def triangle (): #no parameters print(“*”) print(“**”) print(“***”) Now when you call triangle(), it prints those 3 lines.

  11. A simple function definition Function definitions can contain any control structure you like. def triangle(): for i in range(1, 3 + 1): print(“*” * i) This function does the same thing as the previous version. • “Multiplying” a string by an integer repeats the string that many times • “*” * 3 evaluates to “***”

  12. Function arguments Most functions don’t do exactly the same thing every time. • Instead, they take arguments that control the details of what happens • print: what value to print • input: what prompt to display • randrange: what range to choose the random number from • We use arguments to send information into a function • They are the function’s “inputs” • (not the same as user input!)

  13. Parameters and arguments In a function definition, we create placeholders for arguments, called parameters. • Inside the function, parameters work like variables • When you call the function, each argument’s value is stored in the corresponding parameter • It is a run-time error if you give more or fewer arguments than the number of parameters

  14. Parameters and arguments • Call by value: the parameter holds the argument’s value but isn’t the same place in memory as the argument • If you assign a value to the parameter, it does NOT change the argument! • We’ll see later that the situation is more complicated when you have mutable arguments like lists or graphics objects.

  15. A function with a parameter Let’s change our triangle function to take one argument, the height of the triangle (number of lines) def triangle(size): for i in range(1, size + 1): print(“*” * i) Now triangle(3) will print the three-line-high triangle.

  16. A function with a parameter • When triangle is called, the 3 is copied into the parameter size, before executing the body • Remember the terminology! • size is the parameter • 3 is the argument (the value we give the parameter this time) • Note that size is only accessible inside the function • And you set (give a value to) size by calling the function with an argument

  17. Multiple parameters Functions can have more than one parameter def triangle(size, letter): for i in range(1, size+1): print(letter * i) triangle(2, “+”) + ++

  18. Multiple parameters • When calling the function, you must supply the same number of arguments as parameters triangle(3) # ERROR triangle(3, “+”, “-”) # ERROR • If arguments are out of order, or … • if arguments are the wrong type, the function will eventually give an error

  19. Parameters out of order def sum_sub(a, b): return (a + 10) – b If you call this function as sum_sub(1, 3) you get a return value of 8 If you call this function as sum_sub(3, 1) you get a return value of 12 Is this an error? It’s not a syntax error, it MAY be a semantics error depending on the context of the program

  20. Parameters of the wrong type def my_print(a, b): print(a * 2, b) If you call this as my_print(3, 4) it displays 6 4 If you call it as my_print(“abc”, “def”) it displays abcabc def Is this an error? Not a syntax error, it may be semantics error depending on what the function was supposed to do.

  21. Parameters of wrong type On the other hand, using the last version of triangle, If you call it as triangle(“+”, 3), you WILL get an error when the “+” argument is used as the ending point for the range – which must have integers. So Python does NOT check any types when the arguments are passed in. If one of them is the wrong type for how it is USED in the function, then you get the error when that statement is executed.

  22. Returning a value A function can send a value (or values) back to the caller by returning it (or them) • Syntax: return expression or plain: return • Semantics: • First evaluate the expression • Then end the function’s execution (!!) • The value of the function call is the value of the expression, or the special value None if there was no return statement at all

  23. Multiple return values • You can write functions in Python which return more than one thing at the same time def fun sum_and_diff (a, b): return (a+b, a-b) • How do you call it? The simplest way is: x, y = sum_and_diff(9, 5) x gets the first value returned, y gets the second can also be written as (x,y) = sum_and_diff(9,5)

  24. Returning a value • The expression is the “result of” the function • Remember the structured programming guarantees • Each control structure has one exit. • So a function should have one return at the end • If the function doesn’t need to return a value, you can either put a plain return at the end or no return at all. This gives the same result, the function returns to where it was called from.

  25. Parameters/return values vs. input/output • Parameters take “input” from the statement that calls the function • Return values send “output” to the statement that called the function • input() takes input from the keyboard (the user) • print() sends output to the screen (the user) • Good functions usually use parameters and return values, not input and print • Then you can use them not only with user input… • … but also with graphical programs, files, computed data… • When should a function use input or print? • When the function’s sole purpose is to interact with the user

  26. A function that returns a value def triangular_number(num): sum = 0 for i in range(1, num + 1): sum += I return sum When we call the function, run it and see what it returns: print(triangular_number(5)) The function returns 15 The interpreter plugs that value into the expression: print(15) 15

  27. Local variables All the variables defined in a function are local to that function • For example, i in our triangle function • The locals only exist while the function is running • Lifetime or extent: the time during which a variable takes up memory • Variable is “born” when it is initialized… • … and “dies” when the function it is in returns

  28. Local variables • Other functions cannot see local variables at all! • The scope of the variable is which part of the code can see it • The scope of a local variable is the body of the function it is in, starting from its initialization • Scope doesn’t care about what else the function calls! • This means your function cannot refer directly to variables in other functions. • If you need access to information from another function • Use a parameter and argument to send information into a function • Use the return value to get information back out • A global variable is defined outside any function • Avoid these! Very hard to reason about, they can be changed by ANY function at ANY time!

  29. Where to put function definitions • Functions (at least in this class) should be defined at the top level of your source file • Not indented • So NOT inside another function’s definition • Functions must be defined before the code that calls them executes • So if function main calls function triangle: • def triangle must come before the call to main() • But it’s ok if it comes after def main • In general, put the call to main at the end of the file and you’ll be fine

  30. A complete program with functions def main(): number = int(input(“Enter a number: “)) limit = square (number) print(“Counting up to”, limit) countto(limit) def square(x): return x ** 2 def countto (number): for i in range(1, number): print(I, end= “, “) print(number) main() Let’s try rearranging the functions

  31. Documenting functions Functions are “subprograms”, so they should be documented like programs • Write a header comment for each function • Three parts: purpose, preconditions, postconditions • You should still have the usual design comments in the function’s code • Purpose: Describes what the function is supposed to do, in terms of the parameters • Not where it is used: sqrt’s documentation does not say “used in calculation of distance” # Purpose: Compute the sqre of the number x # Purpose: Print a triangle of stars with size rows

  32. Documenting functions • Preconditions: What has to be true before the function is called? • What should the type of each parameter be? • Are there any other restrictions on the parameter values? # Preconditions: x is an integer or a float # Preconditions: size is a positive integer

  33. Documenting functions • Postconditions: what will be true after the function finishes? • What type will be returned, if any? • Any other promises we can make about the return value? • What user input/output will the function have done? # Postconditions: returns a positive number # of the same type as x # Postconditions: Prints size lines to # standard output

  34. Documenting functions • Preconditions and postconditions are like a legal contract • “If you give me this (pre), I promise to give you that (post)” • Helps to identify where a bug could be. If a function does the wrong thing: • If the preconditions are all satisfied, it’s a bug in the function • If they are not, it’s a bug in the caller

  35. Where to put function documentation • In most languages, the 3 P’s (purpose, preconditions, postconditions) are in a comment just before the function definition • Python has another way to do it: documentation strings or “docstrings” • These go inside the function definition, as the very first thing • So it must be indented! • It starts with ‘’’ (three single quotes) • Continues across multiple lines until another ‘’’

  36. Where to put function documentation • Docstrings are not really comments • They still don’t do anything, but the interpreter is aware of them • The help function in the Python shell displays a function’s docstring help(square) # just the function name, no () • You must execute the program first so the definition has been loaded into memory • Example: countsquare-doc.py

  37. Unit testing Functions can be tested in the same way as whole programs • Unit testing: Testing individual functions in isolation • You can verify that the function keeps its promises • Just like a test case for a program. Three columns in the test plan: • Description of the test case • “Normal case, positive integer.” • Inputs: all the arguments you will send to the function • The preconditions • Also list whatever user input is given while it is running • Be sure to indicate which is which! • Expected output: what the function should return and output • The postconditions • Be sure to distinguish the return value from any printed output

  38. Driver functions Once the test plan is written, doing the whole program tests is easy. • Just run the program, type the input and verify the output • But how do we do that with separate functions? • One way: call the function from the shell window • The interpreter will print the return value of the function if you type in a function call • You must run the program at least once as a whole before you can do this – get the functions loaded in memory first!

  39. Driver functions • Another way: write a driver function • A function like main (maybe named tester for example) • But instead of following your design, it just calls the function with the inputs from the unit test • You can check whether the function returned the correct thing! • This is one place where it’s okay to hard-code values, especially for arguments • When you want to run unit tests, just change main() to tester() • An example: countsquare-test.py

  40. Advantages of functions • They avoid repeated code • They allow you to re-use code in a later program • They provide more structure to programs • The details of complicated procedures are hidden away • You can choose to look at the details or at the big picture • Each piece of code deals with one topic • Makes it easier to focus on one part at a time • And for different programmers to work on different parts of the same program at the same time

  41. Advantages of functions • They are easier to test and debug • You can focus on testing one piece at a time • Then put those well-tested pieces together into larger units • Testing at each stage of development means less time spent debugging!

  42. Disadvantages of functions • Functions make the program run slightly slower than just embedding the code. • Arguments have to be copied to parameters, etc. • Some languages (especially compiled ones) avoid this • Every function takes a bit of memory while it is running • Parameters, local variables, “where was I?” • If functions call functions hundreds of calls deep, it could add up to a good piece of memory • Usually only comes up with recursion (a function calls itself) • More lines of code if you only call it once • Two or three extra lines: def, return, and calling the function • If you call it more than a few times, usually it saves lines! Usually the benefits are much higher than the costs!

  43. Single-stepping with functions Remember the three kinds of stepping in the debugger. They have much to do with functions. • Step into: Pause at the next line (maybe at the top of another function) • Step over: Pause at the next line of this function. • Step out: Pause when this function returns Let’s see those in action while watching the call stack

  44. Tracing functions What if you need to trace a program that has functions? • Our traces have a column for the line number • We’ll put the function name on the table too • How do we show variables for each function? • Could have columns for all of them … • … but that could be a lot! • And wouldn’t work with recursive functions • We’ll indicate when we call a function or return from one • Each function has its own table, which disappears when it returns

  45. Tracing with functions: example Let’s trace this program: • def triangular (num): • sum = 0 • for i in range(1, num + 1): • sum += I • return sum • def pyramidal (n): • sum = 0 • for i in range(1, n + 1): • sum += triangular(i) • return sum • def main(): • pyr = pyramidal(2) • print(pyr) • main()

  46. Trace of functions

  47. Trace, continued

  48. Trace, concluded

  49. Debugging functions: the call stack What happens if we set a breakpoint in triangular? • How did we get there? • Called by pyramidal • So we’ll go back there when triangular returns • How did we get to pyramidal? • Called by main • So we’ll go back here when pyramidal returns • When functions return, execution goes back to the calling code • So the interpreter has to keep track of all the calling • Who called the current function, who called them, who called them…

  50. The call stack • The interpreter tracks all this info with a data structure called the call stack • Each item on the call stack is a function call in progress • The local variables for that function are also kept on the stack • Calling causes a new item to be put on top of the stack • Returning removes the item that is on top of the stack • The debugger shows it to you but upside down! • Both WingIDE and IDLE show it in such a way that main() is at the top of the call stack window, new functions are added as you go down • Computer scientists consider the start of any stack as the bottom and add things to the top

More Related