440 likes | 463 Views
Learn how to write your own functions in Python to decompose programs into simpler modules. Includes examples and tips on handling special cases and using parameters.
E N D
COSC 1306COMPUTER SCIENCE AND PROGRAMMING Jehan-François Pâris jfparis@uh.edu
Introduction You will learn to write your own functions Useful to decompose your programs into simpler modules
A simple example Assume you want to compute the average of a list of numbers and you cannot find the Python average function You can do average = sum(…)/len(…)
A better choice You could also define your own function def average(list) : a = sum(list)/len(list) return a Observe the def keyword and the colon the indentation the return keyword
What if your list is empty? It happens! Function will not work Must handle the special case def average(list) : if list == [] : return 0 else : return sum(list)/len(list)
Writing your own function Very easy Write def function_name(parameters) :statementsreturn result Observe the column and the indentation REQUIRED!
What it does Function Result Parameters
Example >>> def maximum (a, b) : if a >= b : max = a else : max = b return max >>> maximum (2, 3)3
Example >>> maximum(2.0, 3) 3 >>> maximum("big", "tall")'tall' >>> maximum('big', 'small')'small' >>> maximum ('a', 3) Does not work: unorderable types: str() >= int()
Multiple return statements >>> def maximum2 (a, b) : if a >= b : return a else : return b >>> maximum2(0, -1)0
No return statement def goodbye() : input('Hit return when you are done.') >>> goodbye()Hit return when you are done.>>>>>> goodbye<function goodbye at 0x00AB0348>
These pesky little details The first line of the function declaration Starts with the keyword def Ends with a column Don’t forget the parentheses when you call a function goodbye()
A second example (I) #firstfunctions.py""" This program contains two functions that convert C into F and F into C ""“def celsius (temperature) : return (temperature - 32)*5/9def fahrenheit (temperature) : return (temperature*9/5 + 32)
A second example (II) degrees = float(input('Enter a temperature: '))print('%.1f Fahrenheit is same as' % degrees + ' %.1f Celsius' % celsius(degrees))print('%.1f Celsius is same as' % degrees + ' %.1f Fahrenheit' % fahrenheit(degrees))input('Hit return when you are done')
Creating a module Put the functions in a separate file #twofunctions.py""" This module contains two functions""“def celsius (temperature) : return (temperature - 32)*5/9def fahrenheit (temperature) : return (temperature*9/5 + 32)
Using a module #samefunctions.py""" This program calls two functions.""“from twofunctions import celsius, fahrenheitdegrees = float(input('Enter a temperature: '))…
These pesky little details Module name must have .py suffix import statement should contain module name stripped of that suffix
Parameters w/ default values >>> def aftertax( price, taxrate = 0.0825) : return price*(1 + taxrate) >>> aftertax(100)108.25 >>> aftertax(100, 0)100 >>> aftertax(200, 12)224
Why you should write functions Makes your code more readable Hides the details Keeps each piece of code shorter Allows you to reuse your work
What happens in a functionshould stay in the function Python helps you by using different variables inside this function There are still problems with parameters
The good news def ssq(n) : sum = 0 for i in range(1, n+1) : sum += i*i return sum n = 5sum = -1 # totally unrelatedprint('sum = %d' % sum)print ('sum of squares up to %d: %d' %(n, ssq(n)))print('sum = %d' % sum) # sum is unchanged Not the same sum variable as in the calling program
The rule When you use a variable inside a function, it will remain local to the function Even if a variable with the same name is used outside the function Great rule: You can use any variable name inside a function without having to worry about possible conflicts
What about parameters Things are different when you modify inside a function a "mutable" parameter lists, dictionaries, sets but not numbers, strings and tuples All the changes brought to them will be reflected in the calling program Not always what we wanted Do not worry about these last two yet Ditto
A bad program def bad_average(student) : student.pop(0) if len(student) > 0 : return sum(student)/len(student) else : return 0 lst = ['John Doe', 80, 85, 90 ]print(bad_average(lst))print(lst) # will return [80, 85, 90] We change the value of the parameter Unwanted side-effect
A much better program def good_average(student) : grades = student[1:] if len(grades) > 0 : return sum(grades)/len(grades) else : return 0 lst = ['John Doe', 80, 85, 90 ]print(good_average(lst))print(lst) # will print ['John Doe', 80, 85, 90 ]
Computing the square root (I) Want a simple algorithm to compute √s of a positive number. If x = √s then x2 = s and x = s/x Consideran approximation a of √s If a < √s then s/a >√s If a > √s then s/a <√s In either case, √s is between a and s/a STEM Students only
Computing the square root (II) The average of a and s/a(a + s/a)/2is a better estimate of √s If a < x x is inside 0 a s/a If a > x x is inside 0 s/a a
New Problem When should we end? When our result is accurate enough When the interval (a, s/a) is small enough Checking a – s/a < epsilon will not work
New Problem When should we end? When our result is accurate enough When the interval (s, s/a) is small enough Checking a – s/a < epsilon will not workbecause a – s/a can be negative Must check abs(a – s/a) < epsilon
First attempt s = float(input("Enter a positive number: "))a = 1sovera = s/aprint("Root is between %.3f and %.3f" % (s, a, sovera))while abs(a - sovera) > 10e-6 : a = (a + sovera)/2 sovera = s/aprint("The square root of %.6f is %.6f" % (s, a))
Criticism Two big issues We normally need to compute a square root inside another computation Make it a function "square root" We do not let the user specify the precision Should let the user enter it
Second attempt def mysqrt (s) :a = 1 sovera = s/a while abs(a - sovera) > 10e-6 : a = (a + sovera)/2 sovera = s/a return an = float(input("Enter a positive number: "))answer = mysqrt(n)print("The square root of %.6f is %.6f" % (number, answer))
Explanations Function is defined—or declared—within def function_name(parameter_list) : … return(…) return specifies which values should be returned by a function A function can have several return statements
Example """Maximum of two numbers """def mymax(a, b) : if a > b : return a else : return b
Third attempt """ Square root with arbitrary precision """def mysqrt (s, epsilon) : a = 1 sovera = s/a while abs(a - sovera) > epsilon : a = (a + sovera)/2 sovera = s/a return a
Criticism Not everybody wants to specify a precision Should make it optional
Fourth attempt """ Square root with arbitrary precision """def mysqrt (s, epsilon = 0.00001) : a = 1 sovera = s/a while abs(a - sovera) > epsilon : a = (a + sovera)/2 sovera = s/a return a
Default parameters If we give a default value to a parameter of the function, this parameter can be omitted
Built-in functions print(…) is always available Other functions are parts of modules sqrt(…) is part of math module Before using any of these functions we must import them from math import sqrt from random import randint, uniform Don't forget the comma!
More about modules We can write our own modules Can be situations where two or more modules have functions with the same names Solution is to import the modules import math Can now use all functions in module Must prefix them with module namemath.sqrt(…)
Your two choices When you want to use the function sqrt( ) from the module math, you can either use from math import sqrtand refer directly to sqrt( ) import mathand refer to the function as math.sqrt()
Good practice rules Put all your import and use statements at the beginning of your program Makes the programmore legible As soon as you use several modules,avoid import from ….. Easier to find which function comes from which module