Introduction to Programming in Python ===================================== 1) Let's review the characteristics of imperative languages: 1.1) What are the main differences between imperative and functional languages? 2) Normally we say that a functional language has expressions, and an imperative language has commands and expressions. What is a command? 2.1) There are three major types of commands: - Branches - Conditionals - Iterations - Sequences - Blocks - Assignments 3) Perhaps the archetype imperative command is the assignment. We have not seen assignments in SML, yet, we have seen programs such as - let val a = 2 val b = 3 in a + b end; Why is 'val a = 2' not an assignment 3.1) What is then the semantics of an assignment? The issue of portability. A little of the history of Python. 3.2) Why is Python so popular? - SciPy: 2001 - NumPy: 2006 - Pandas: 2008 - Coursera/EdX: 2012 - Project Jupyter: 2015 The popularity of Python: http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html The guiding principles behind python: >>> import this 4) What is the meaning of 'Explicit is better than implicit.' 5) Python is a dynamic language. What is this? - heavy use of the heap 5.1) This is not an exclusive characteristic of dynamic languages. Which other languages use the heap heavily? - dynamic typing >>> if 2 != 3: ... a = "fernando" ... else: ... a = 0 5.2) How could you write a similar program in C, SML or Java? - eval and exec a = 1 exec 'a = a + 1' print a 5.3) Notice that you are changing a variable in your scope. How could you write a similar program in C, SML or Java? 6) Python programs are interpreted or virtualized. What does this mean? 7) Normally these programs are parsed, transformed in some sort of intermediate representation, and then executed in a virtual machine. There exist JIT compilers for Python, e.g., Numba, but they are not default. 7.1) What is a VM? 7.2) What is an intermediate representation? 7.3) What is JIT compilation? 8) How to execute python programs? - Interactive interpreter: $> python >>> 2 + 3.0 5.0 - Loading a file: $> echo "print \"Hello, world\"" > hello.py $> python hello.py - As an executable script $> cat script.py #! /usr/bin/env python print "Hello, world!" $> chmod u+x script.py $> ./script.py Types in python are verified during the program execution; however, the types do exist! 9) Python does not really have primitive types (they are all objects), but there are types with builtin syntax. 9.1) What are the primitive types in SML? 9.2) Which builtin types are we likely to find in Python? - integer numbers: >>> (50-5*6)/4 5 - floating point numbers: >>> (50 - 5.0 * 6) / 4 5.0 - Strings: >>> s = "Fernando" + " Magno" >>> print s Fernando Magno 9.3) Explain the difference between primitive and built in. - Booleans >>> 3 > 2 True 10) What are the operators of the language? * / % + - << >> < > <= >= == != ~ & ^ | not and or = += -= *= /= %= &= ^= |= <<= >>= 11) Compared to C, what are we really missing? exp++ exp-- ++exp --exp 11.1) Does python have conditional expressions, like ternary comparisons in C? v = 1 if 0 else "oi" v = 1 if False else "oi" v = 1 if None else "oi" 12) Comparisons can be chained, e.g a < b == c. How to code a function inbetween(a, b, c)? >>> def inbetween(a, b, c): return a <= b <= c ... >>> inbetween(2, 3, 3) True >>> inbetween(2, 3, 2) False 13) We see many assignments. An assignment has a left side and a right side. What can exist on the right side? 13.1) What about the left side? 13.2) What is the meaning of >>> x = y = z = 0 14) What are compound data types? Which compound data types are we likely to find in Python? - Lists: >>> a = ['spam', 'eggs', 100, 1234] >>> a ['spam', 'eggs', 100, 1234] >>> a[0] 'spam' >>> a[3] 1234 >>> a[-2] 100 >>> a[1:-1] ['eggs', 100] >>> a[:2] + ['bacon', 2*2] ['spam', 'eggs', 'bacon', 4] >>> 3*a[:3] + ['Boe!'] ['spam', 'eggs', 100, 'spam', 'eggs', 100, 'spam', 'eggs', 100, 'Boe!'] 15) Strings have some list operations too, but strings are not lists. Why? E.g: >>> a = "dcc024" >>> a[0] 'd' >>> a[-1] '4' >>> a[1:-1] 'cc02' >>> a[0] = 'x' Traceback (most recent call last): File "", line 1, in TypeError: 'str' object does not support item assignment - It is possible to do a lot of things with list slices: >>> # Replace some items: ... a[0:2] = [1, 12] >>> a [1, 12, 123, 1234] >>> # Remove some: ... a[0:2] = [] >>> a [123, 1234] >>> # Insert some: ... a[1:1] = ['bletch', 'xyzzy'] >>> a [123, 'bletch', 'xyzzy', 1234] >>> a[:0] = a # Insert (a copy of) itself at the beginning >>> a [123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234] 16) How to code a function duplist that receives a list l, and updates l, so that the new list is l + l? def duplist0(l): l[:0] = l 16.1) How to do it without side effects? def duplist1(l): return l + l 17) Ok, we have seen lists, what else are we missing from SML? >>> t = 12345, 54321, 'hello!' >>> t[0] 12345 >>> t (12345, 54321, 'hello!') >>> # Tuples may be nested: ... u = t, (1, 2, 3, 4, 5) >>> u ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5)) 18) How to create a tuple with 0 or 1 items? >>> empty = () >>> singleton = 'hello', # <-- note trailing comma >>> len(empty) 0 >>> len(singleton) 1 >>> singleton ('hello',) - We can also do some sort of pattern matching in tuples: >>> x, y, z = t 19) Finally, we also have dictionaries as built in compound types. What is a dictionary? >>> tel = {'jack': 4098, 'sape': 4139} >>> tel['guido'] = 4127 >>> tel {'sape': 4139, 'guido': 4127, 'jack': 4098} >>> tel['jack'] 4098 >>> del tel['sape'] >>> tel['guido'] = 4127 >>> tel {'guido': 4127, 'irv': 4127, 'jack': 4098} >>> tel.keys() ['guido', 'irv', 'jack'] >>> tel.has_key('guido') True >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} >>> for k, v in knights.items(): ... print (k, v) ... gallahad the pure robin the brave 20) The main compilable unit in Python is the function: def sum(a, b): return a + b 21) What was the main "control flow structure" that we have used in SML? 21.1) Imperative languages provide many control flow structures. Examples? - if/elif/else: 22) How to code a recursive factorial function? def fact(n): if n > 1: return n * fact (n - 1) elif n == 1 or n == 0: return 1 else: raise ArithmeticError("Factorial needs positive integers!") print fact(1) print fact(-1) 23) How to go over the elements of a list? - for: ... a = ['cat', 'window', 'defenestrate'] >>> for x in a: ... print (x, len(x)) ... - for + range: >>> a = ['Mary', 'had', 'a', 'little', 'lamb'] >>> for i in range(len(a)): ... print (i, a[i]) ... 24) What does the program below do? - break and else inside loops: def mystery(n): for x in range(2, n): if n % x == 0: print (n, 'equals ', x, ' * ', n/x) break else: print (n, ' passes the test!') 25) How to implement a factorial using a while loop? - while: def factW(n): ans = 1 while n > 1: ans *= n n -= 1 return ans 26) What would happen if I tried: def factW(n): ans = 1 while n > 1: ans *= n n -= 1 // moved this statement two spaces left return ans 27) What are the advantages and disadvantages of adding block semantics to indentation? 27.1) How to leave two commands in the same line? def factW(n): ans = 1 while n > 1: ans *= n ; n -= 1 return ans 27.2) Do you know other languages where identation is significant? 28) Do you remember what are first class values? 28.1) How to know if functions in python are first class values? - Functions in Python are first class values: >>> f = factW >>> f(7) 5040 29) Do you remember what are high-order functions? 29.1) How to know if python has high-order functions? def computeFacts(f, l): for x in l: print (x, f(x)) 30) Do you remember what are closures? 30.1) How to code something like \n . \x . x + n ? def make_incrementor(n): def inc(x): return x + n return inc - or - >>> def make_incrementor(n): ... return lambda x: x + n ... >>> f = make_incrementor(42) >>> f(0) 42 - or - >>> f = lambda x : lambda y : x + y >>> a = f(3) >>> a(2) 5 31) Have you ever heard about list comprehension? >>> [3*x for x in vec] [6, 12, 18] >>> [3*x for x in vec if x > 3] [12, 18] 31.1) Code a function that returns the strings that start with 'a' in a list of strings: def filterC(c, l): return [s for s in l if s[0] == c] >>> filterC('a', ['abacate', 'uva', 'ameixa', 'banana', 'abacaxi']) ['abacate', 'ameixa', 'abacaxi'] >>> filterC(1, [(1, 2), (3, 4), (1, 3)]) [(1, 2), (1, 3)] >>> filterC(1, [(1, 2), (3, 4), [1, 2, 3], (1, 3)]) [(1, 2), [1, 2, 3], (1, 3)] >>> filterC(1, [(1, 2), (3, 4), [1, 2, 3], "1, 2, 3", (1, 3)]) [(1, 2), [1, 2, 3], (1, 3)] >>> filterC("1", [("1", 2), (3, 4), [1, 2, 3], "1, 2, 3", (1, 3)]) [('1', 2), '1, 2, 3'] >>> filterC("1", [("1", 2), (3, 4), [1, 2, 3], "1, 2, 3", (1, 3)]) 31.2) List comprehension also works on dictionaries. Write a function that converts a string S into a dictionary of words (in S) and their lengths. >>> def strLen(L): ... return {key:len(key) for key in L.split()} ... >>> strLen("Fernando Magno Quintao Pereira") {'Magno': 5, 'Pereira': 7, 'Fernando': 8, 'Quintao': 7} # Map, reduce 32) How to code, in SML, a function that maps the elements in a list of integers to their cubes? 32.1) How to do the same in Python? map(lambda n: n * n * n, range(1, 11)) 33) How to code a function that sums up the elements in a list, in SML? 33.1) How to do the same in Python? >>> from functools import reduce >>> def sum(l): return reduce(lambda a, b: a + b, l, 0) ... >>> sum([1,2,3,4]) 10 34) Modifying the syntax of the language (in Python 2): >>> 11/4 2 >>> from __future__ import division >>> 11/4 2.75 35) It is very important to be able to check the type of a variable at runtime. Why this is particularly important in Python? 35.1) How to do it? >>> a = None >>> type(a) >>> a = 'a' >>> type(a) >>> a = ['a', 0] >>> type(a) 36) Write a function that divides two numbers, n and d. This function should return the special element None in case d == 0: def div(n, d): if d == 0: return None else: return n/d 37) Now, write a function that uses div, and check if the answer is None: def testDiv(): while True: n = float(input("Please, enter the dividend: ")) d = float(input("Please, enter the divisor: ")) a = div(n, d) if type(a) == type(None): break else: print(a) 38) How to discover if two strings are anagrams? def anagrams(s1, s2): if (len(s1) != len(s2)): return False else: table = {} for c in s1: if c in table: table[c] += 1 else: table[c] = 1 for c in s2: try: table[c] -= 1 if table[c] == 0: table.pop(c) except KeyError: return False return True