450 likes | 640 Views
Programming for Engineers in Python. Recitation 3. Plan. Modules / Packages Tuples Mutable / Imutable Dictionaries Functions: Scope Call by Ref / Call by Val Frequency Counter. Python Code Hierarchy. Statement. function. Module. Package. Modules.
E N D
Programming for Engineers in Python Recitation 3
Plan • Modules / Packages • Tuples • Mutable / Imutable • Dictionaries • Functions: • Scope • Call by Ref / Call by Val • Frequency Counter
Python Code Hierarchy Statement function Module Package
Modules All modules and their contents (functions, constants) can be found at http://docs.python.org/modindex.html >>>import math # mathematical functions >>>dir(math) ['__doc__', '__name__', '__package__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', 'gamma', 'hypot', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'trunc'] >>> math.pi # a constant 3.141592653589793 >>> math.sqrt(16) # a function 4.0 >>> math.log(8, 2) 3.0
Modules – Cont. >>> import os #operating system interfaces >>> os.rename(‘my_file.txt’, ‘your_file.txt’) >>> os.mkdir(‘new_dir’) >>> for root, dirs, files in os.walk('lib/email'): print root, "consumes", printsum(getsize(join(root, name)) for name in files), print"bytes in", len(files), "non-directory files" >>> os.times()[0] # user time 10.1244649
Packages • NumPy • support for large, multi-dimensional arrays and matrices • high-level mathematical functions • SciPy • Optimization • linear algebra • integration • special functions • signal and image processing And more
Installing Packages Download NumPy: http://sourceforge.net/projects/numpy/files/NumPy/ Choose Download numpy-1.6.1-win32-superpack-python2.7.exe SciPy: http://sourceforge.net/projects/scipy/files/ Choose Download scipy-0.9.0-win32-superpack-python2.6.exe
Mutable vs. Immutable Can we change lists? >>>a_list = [1,2,3] >>>a_list[2] 3 >>>a_list[2] = ‘Inigo Montoya’ >>>a_list [1,2,’Inigo Montoya’] The assignment has mutated the list!
Mutable vs. Immutable What about strings? >>> name = ‘Inigo Montoya’ >>> name[0] ' I' >>>name[5] ' ' >>>name[3] = ‘t’ Traceback (most recent call last): File "<pyshell#14>", line 1, in <module> name[3] = 't' TypeError: 'str' object does not support item assignment Immutable!
Assignments to List Variables >>>orig_list = [1,2,3] >>>copy_list = orig_list >>>orig_list = [6,7,8,9] >>>copy_list [1,2,3] >>> orig_list [6,7,8,9] So far - no surprises
Assignments to List Variables >>> copy_list = orig_list >>>orig_list[0] = 1000 >>>orig_list [1000,7,8,9] >>>copy_list [1000,7,8,9] Surprise!
Assignments to List Variables List assignment orig_list = [6,7,8,9] creates: • a list object, [6,7,8,9] • a reference from the variable name, orig_list, to this object. Memory Memory orig_list [6,7,8,9]
Assignments to List Variables The assignment copy_list = orig_listdoes not create a new object, just a new variable name, copy_list, which now refers to the same object. Memory orig_list [6,7,8,9] copy_list
Assignments to List Variables Mutating list elements, orig_list[0] = 1000, does not create a new object and does not change existing references. Memory orig_list [1000,7,8,9] copy_list
Tuples A tuple is just like a list, only it is immutable. Syntax: note the parentheses! >>>t = (‘don’t’,’worry’,’be’,’happy’)# definition >>>t (‘dont’,’worry’,’be’,’happy’) >>>t[0] # indexing 'dont' >>>t[-1] # backwords indexing ‘worry' >>>t[1:3] # slicing (’worry’,’be’)
Tuples >>> t[0] = ‘do’ # try to change Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> t[0]=‘do’ TypeError: 'tuple' object does not support item assignment No append / extend / remove in Tuples!
Tuples So what are tuples good for? • Faster than lists • Safe code • When immutable types are required (coming next).
Dictionaries A dictionary is a set of key-value pairs. >>> dict_name = {key1:val1, key2:val2,…} Keys are unique and immutable, values are not. Example: Map names to heights: >>> heights = {‘Alan Harper’:1.76, ‘John Smith’:1.83, ‘Walden Schmidt’:1.90} >>> heights {'Walden Schmidt': 1.9, 'John Smith': 1.83, 'Alan Harper': 1.76} Note:The pairs order changed
Dictionaries Add a new person: >>> heights[‘LyndseyMakelroy’] = 1.70 >>> heights {'LyndseyMakelroy': 1.7, 'Walden Schmidt': 1.9, ‘John Smith': 1.83, 'Alan Harper': 1.76} What happens when the key already exists? >>> heights[‘John Smith’] = 2.02 >>> heights {'LyndseyMakelroy': 1.7, 'Walden Schmidt': 1.9, 'John Smith': 2.02, 'Alan Harper': 1.76} Solutions?
Dictionaries Idea: Add address to the key >>> heights = {[‘Alan Harper’, ‘Malibu’]:1.76} Traceback (most recent call last): File "<pyshell#46>", line 1, in <module> heights = {['Alan Harper', 'Malibu']:1.76} TypeError: unhashable type: 'list‘ What’s the problem? Fix: >>> heights = {(‘Alan Harper’, ‘Malibu’):1.76} >>> heights {('Alan Harper', 'Malibu'): 1.76}
Dictionaries Useful methods: • D.get(k[,d]) - D[k] if k in D, else d (default – None). • D.has_key(k) - True if D has a key k, else False • D.items() - list of (key, value) pairs, as 2-tuples • D.keys() - list of D's keys • D.values() - list of D's values • D.pop(k[,d]) - remove specified key and return the value. If key is not found, d is returned.
Functions – Scope Consider the following function, operating on two arguments: deflinear_combination(x,y): y=2*y return (x+y) The formal parameters x and y are local, and their “life time" is just the execution of the function. They disappear when the function is returned. linear_combination x, y 3, 4 11
Functions – Scope >>> a=3 >>> b=4 >>> linear combination(a,b) 11 # this is the correct value >>> a 3 >>> b 4 # b has NOT changed The change in y is local - inside the body of the function.
Functions – Scope >>> x=3 >>> y=4 >>> linear_combination(x,y) 11 # this is the correct value >>> x 3 >>> y 4 The y in the calling environment and the y in the function are not the same variable!
Functions – Call by Val / Call by Ref Functions have arguments that appear in their prototype: deflinear_combination(x,y): When you call a function, you must assign values to the function’s arguments: >>> linear_combination(3, 4) What happens when you pass variables? >>> linear_combination(a, b)
Functions – Call by Val / Call by Ref What is the difference? Run ta3_switch.py to find out!
Functions – Call by Val / Call by Ref What is the difference? Run ta3_add.py to find out!
Functions – Call by Val / Call by Ref There are two possibilities: • Call by Value – pass a’svalue to x and b’s value to y • Call by Reference – pass a’s address to x and b’s address to y A_function x = 3 y = 4 a, b a=3 b=4 Another_function x y a, b a=[1,2] b=[3, 4]
Functions – Call by Reference In Python – Call by reference A function can mutate its parameters. When the address does not change, the mutations effect the original caller's environment. Remember: Assignment changes the address! That explains why y=2*yis not visible in the caller's environment.
Functions – Call by Reference def increment(lst): for i in range(len(lst)): lst[i] = lst[i] +1 # no value returned Now let us execute it in the following manner >>> list1=[0,1,2,3] >>> increment(list1) >>> list1 [1, 2, 3, 4] # list1 has changed! lstwas mutated inside the body of increment(lst). Such change occurs only for mutable objects.
Functions – Call by Reference Consider the following function: def nullify(lst): lst=[ ] # no value returned Now let us execute it in the following manner >>> list1=[0,1,2,3] >>> nullify(list1) >>> list1 [0, 1, 2, 3] # list1 has NOT changed! Why?
Functions - Information Flow To conclude, we saw two ways of passing information from a function back to its caller: • Using return value(s) • Mutating a mutable parameter
Frequency Counter • Assume you want to learn about the frequencies of English letters. • You find a long and representative text and start counting. • Which data structure will you use to keep your findings? s u percali f ragili s ticexpialidociou s
Frequency Counter str1 = 'supercalifragilisticexpialidocious‘ # count letters charCount = {} for char in str1: charCount[char] = charCount.get(char, 0) + 1 # sort alphabetically sortedCharTuples = sorted(charCount.items())
Frequency Counter # print forcharTupleinsortedCharTuples: printcharTuple[0] , ‘ = ‘,charTuple[1] a = 3 c = 3 d = 1 e = 2 f = 1 g = 1 …
Simulation – Reminder • In class: • Simulated a rare disease by: • Generating its distribution in the entire population, assume we received 2% • Generating a sample of 1000 people. For every person – “toss a coin” with 2% chance of “heads” (have the disease) and 98% of “tails” (don’t have the disease) • Check whether the number of sick people is significantly higher then expected (20 people) • Repeat for 100 diseases
Simulation - Cards Scenario: • Generate 25 playing cards. • Guess which series every card belongs to. • One card - there is an equal chance that the card belongs to each of the four series, hence - 25% chance for being correct. • Two cards – 16 options with equal chance 6.25% chance • n cards – 4n options, 1/ 4n chance of being correct in all guesses. For 25 cards the chance of being always correct drops to almost 0.
Exercise - Dice Odds In backgammon, there are 36 combinations of rolling the dice. We are interested in the sum of the two dice. Therefore: • count the number of combinations for every possible sum • find the chance of getting it.
Exercise - Dice Odds Create the following data structure: • Each combination of two dice is a tuple. • All combinations are held in a dictionary, where the key is the sum of the combination. • Each value in the dictionary is a list of tuples – that is, all combinations that sum to key Keys Values [ (1 , 1) ] 2 [ (1 , 2) , (2, 1) ] 3 [ (1 , 3) , (2 , 2) , (3 , 1) ] 4
Exercise - Dice Odds The general outline is: rolls = {} Loop with d1 from 1 to 6 Loop with d2 from 1 to 6 newTuple ← ( d1, d2 ) # create the tuple oldList ← dictionary entry for d1+d2 newList ← oldList + newTuple update dictionary entry Loop over all keys in the dictionary print key, length of the list Let’s Play!
Exercise - Dice Odds rolls = {} for d1 inrange(1, 7): # first dice for d2 inrange(1, 7): # second dice t = (d1, d2) key = d1+d2 val = rolls.get(key, []) # update list val.append(t) rolls[key] = val for key inrolls.keys(): # print result print key, len( rolls[key] )
Exercise - Dice Odds >>> 2 1 3 2 4 3 5 4 6 5 7 6 8 5 9 4 10 3 11 2 12 1