Functions, Local and Global Variables ------------------------------------- - So far, we have seen many different types of built-in functions. #. Functions that return a new value given some arguments (and not change any values). >>> name = 'Rick' >>> len(name) 4 >>> name*2 'RickRick' #. Functions that return a new value, but apply directly to an input variable, but does not change that variable: :: >>> valstr = "1,2,3" >>> vals = valstr.split(",") >>> vals ['1', '2', '3'] We saw this in strings mostly. #. Functions that return nothing and change the variable they are applied to. We have seen this in containers and Images, because this requires a complex type. See how they are called: :: >>> animals ['dog', 'cat', 'pig'] >>> animals.sort() >>> animals ['cat', 'dog', 'pig'] >>> animals.append('cow') >>> animals ['cat', 'dog', 'pig', 'cow'] See there is no assignment here, just calling a function. #. Rare case of a function that returns something and also modifies the input variable. :: >>> animals ['cat', 'dog', 'pig', 'cow'] >>> >>> animals ['cat', 'dog', 'pig', 'cow'] >>> animal = animals.pop() >>> animal 'cow' >>> animals ['cat', 'dog', 'pig'] Writing our own functions -------------------------- - When writing functions, you must provide all the values the function accesses to be either given as an argument or defined locally. This means, the function is well encapsulated. :: def find_area(radius): import math area = math.pi * radius**2 return area This function can be read and understood regardless of which program it is in. It does not need any value outside of its definition. Parameter: radius Local variable: area It needs nothing else. Functions that return something ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - We have seen how to write a function that returns something (with a return statement). :: def find_area(radius): import math area = math.pi * radius**2 return area if __name__ == "__main__": rad = 10 ## this is global variable rad myarea = find_area(rad) ## pass value of rad to function, ## and assign returned value to global variable myarea print myarea Here rad and myarea are global variables, while radius and area are local variables. - What happens when local variables have the same name as global variables? :: def find_area(radius): import math area = math.pi * radius**2 return area if __name__ == "__main__": radius = 10 ## this is global variable radius area = 100 print find_area(radius) print area When the function is executing, it looks for the nearest place a variable is defined. For the line: :: area = math.pi * radius**2 We will first start looking above this line in the function, all the way to the definition. Given it is in the argument, we will use the local radius variable. If it was not defined, we would look outside of the function, assuming that a variable with this name is defined in the program. This would be using a global variable, we do not want this. Also note that when we change the local variable area, we do not change the global variable area. They are two different variables. It is best to name your local and global variables differently to avoid confusion, until you are very comfortable with variable scopes. Functions that return nothing and change no values ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - This is often preserved for functions that print something (we will see exception for lists below). - You must still not access global variables to print. - The main distinction is how we call these functions. :: def print_area(radius): import math area = math.pi * radius**2 print "The area of circle with radius: %d is: %.2f" %(radius, area) if __name__ == "__main__": radius = 10 ## this is global variable radius print_area(radius) These functions are especially useful for formatting. Functions that return nothing but change values ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - When writing functions over lists, we still do not want to use global variables. - A list valued argument that is passed to a function parameter becomes an alias. So, if the list is changed in the function, it is changed in the program too. - Best practice: if you have a function that modifies a list, do not return a value. It is less confusing to find out what the function does. :: def cap_list(L): for i in range(len(L)): L[i] = L[i].capitalize() if __name__ == "__main__": animals = ['dog','cat','pig'] cap_list(animals) print animals In this program, when we call the function cap_list, animals and L become aliases to the same list. This way, we are able to capitalize the elements in the list.