Python Crash Course Programming 3rd year Bachelors V1.0 dd 03-09-2013 Hour 1 Good programming practice • Compromise between: – producing results quickly and – easy reusability and adaptation of code – code that can be quickly understood by others • • • • Comment clearly Use functions Use modules Consider ‘refactoring’ before code gets too messy • Science, not software development Introduction to language - conditionals >>> a = 4; b = 3 >>> if a > b: ... result = ‘bigger’ ... c = a - b ... >>> print(result, c) bigger 1 >>> a = 1; b = 3 >>> if a > b: ... result = ‘bigger’ ... elif a == b: ... result = ‘same’ ... else: # i.e. a < b ... result = ‘smaller’ ... >>> print(result) smaller >>> if a < b: print ‘ok’ ok • Indentation is important! – be consistent – use four spaces – do not use tabs Comparison operators: == != > < >= <= is is not in not in Boolean operators: and or not Membership and Identity Operators There are two membership operators explained below: Operator Description Example in Evaluates to true if it finds a x in y, here in results in a 1 if x variable in the specified is a member of sequence y. sequence and false otherwise. not in Evaluates to true if it does not x not in y, here not in results in finds a variable in the a 1 if x is a member of sequence specified sequence and false y. otherwise. There are two Identity operators explained below: Operator Description Example is Evaluates to true if the variables on either side of the operator point to the same object and false otherwise. x is y, here is results in 1 if id(x) equals id(y). is not Evaluates to false if the variables on either side of the operator point to the same object and true otherwise. x is not y, here is not results in 1 if id(x) is not equal to id(y). Operators Precedence The following table lists all operators from highest precedence to lowest. Operator Description ** Exponentiation (raise to the power) ~+- Ccomplement, unary plus and minus (method names for the last two are +@ and -@) * / % // Multiply, divide, modulo and floor division +- Addition and subtraction >> << Right and left bitwise shift & Bitwise 'AND' ^| Bitwise exclusive `OR' and regular `OR' <= < > >= Comparison operators <> == != Equality operators = %= /= //= -= += *= **= Assignment operators is is not Identity operators in not in Membership operators not or and Logical operators Indentation rules • • • • • • Top level must not be indented It does not matter how much blanks you use, but: Uniform within each block Better avoid tabs Most people use 4 blanks per level If you use emacs python mode, defaults are OK Introduction to language - conditionals >>> if 'Steven' in ['Bob', 'Amy', 'Steven', 'Fred']: ... print 'Here!' ... Here! >>> if 'Carol' not in ['Bob', 'Amy', 'Steven', 'Fred']: ... print 'Away!' ... Away! >>> test = a == b >>> if test: print 'Equal' 'Equal' >>> >>> ... ... ... ... ... ... ... ... ... ... x = int(raw_input("Please enter an integer: ")) if x < 0: x = 0 print 'Negative changed to zero' elif x == 0: print 'Zero' elif x == 1: print 'Single' elif x == 2: Print 'Double' else: print 'More' Introduction to language - truth Boolean expression can combine different datatypes: >>> >>> >>> >>> >>> >>> >>> >>> 0 or "not empty" False or "" or [1,2,3] or 42 42 and [1,2,3] [1,2,3] and 42 # Boolean expressions are evaluated # from left to right and return the value # that determines result # (Short-circuit evaluation Equality and Identity >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> l = [1,2,3] m = l # Equality (of l == m # Identity (of l is m # l and id(l) id(m) l[0] = 42 print l print m # m[0] values) tested with == objects) tested with is m same object! = ? Comparisons yield Boolean values Other datatypes can also express truth: >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> ... ... ... t = 1==1 # Boolean: True f = 0==1 # Boolean: False # Boolean operators: t and False True or f not True # Precedence: ( > not > and > or: False or True and not False (not False or True) == (not (False or True)) x = 42 if x: print "true" else: print "false" Introduction to language - loops >>> >>> ... ... ... 3 6 9 12 >>> ... ... ... 3 6 9 >>> >>> a = b = 0 while a < 10: a += 3 print(a) while True: b += 3 if b >= 10: break print(b) >>> for i in [2, 5, 3]: ... print(i**2) 4 25 9 >>> for j in range(5): 0 1 2 3 4 print(j) >>> range(3, 10, 2) [3,5,7,9] a = 0 while a < 5: a +=1 >>> d = >>> for ... this is that is {'this': 2, 'that': 7} k, v in d.items(): print('%s is %i'%(k, v)) 2 7 Introduction to language - Loop control The most common use for break is when some external condition is triggered requiring a hasty exit from a loop. The break statement can be used in both while and for loops. The continue statement in Python returns the control to the beginning of the while loop. The continue statement rejects all the remaining statements in the current iteration of the loop and moves the control back to the top of the loop. #!/usr/bin/python #!/usr/bin/python for letter in 'Python': # First Example if letter == 'h': break print 'Current Letter :', letter for letter in 'Python': # First Example if letter == 'h': continue print 'Current Letter :', letter Current Letter : P Current Letter : y Current Letter : t Current Current Current Current Current Letter Letter Letter Letter Letter : : : : : P y t o n Introduction to language - Loop control An else statement associated with a loop statements. • If the else statement is used with a for loop, the else statement is executed when the loop has exhausted iterating the list. • If the else statement is used with a while loop, the else statement is executed when the condition becomes false. #!/usr/bin/python for num in range(10,17): for i in range(2,num): if num%i == 0: j=num/i print '%d equals %d * %d' % (num,i,j) break else: print num, 'is a prime number‘ 10 11 12 13 14 15 16 17 equals 2 * is a prime equals 2 * is a prime equals 2 * equals 3 * equals 2 * is a prime 5 number 6 number 7 5 8 number The pass statement is used when a statement is required syntactically but you do not want any command or code to execute. The pass statement is a null operation; nothing happens when it executes. The pass is also useful in places where your code will eventually go, but has not been written yet #!/usr/bin/python for letter in 'Python': if letter == 'h': pass print 'This is pass block' print 'Current Letter :', letter print "Good bye!" Current Letter : P Current Letter : y Current Letter : t This is pass block Current Letter : h Current Letter : o Current Letter : n Good bye! Documentation and tests >>> # My totally wicked function >>> def my_func(x, y=0.0, z=1.0): ... ”””This does some stuff. ... For example: >>> my_func(1.0, 3.0, 2.0) 8.0 Yep, it’s that good! ””” ... a = x + y ... b = a * z ... return b • Comments before function, class, etc. are used to generate help • “Docstrings” – preferred way of documenting code – can contain examples, which are automatically turned into tests! • See doctest module Unittests import unittest •classmakes each code test itself for error free functioning TestSequenceFunctions(unittest.TestCase): – example from random module code def setUp(self): self.seq = range(10) def testshuffle(self): # make sure the shuffled sequence does not lose any elements random.shuffle(self.seq) self.seq.sort() self.assertEqual(self.seq, range(10)) def testchoice(self): element = random.choice(self.seq) self.assert_(element in self.seq) def testsample(self): self.assertRaises(ValueError, random.sample, self.seq, 20) for element in random.sample(self.seq, 5): self.assert_(element in self.seq) if __name__ == '__main__': unittest.main() Good programming • Code layout – 4 spaces indentation – continue sensibly # Aligned with opening delimiter foo = long_function_name(var_one, var_two, var_three, var_four) # More indentation included to distinguish this from the rest. def long_function_name( var_one, var_two, var_three, var_four): print(var_one) my_list = [ 1, 2, 3, 4, 5, 6, ] result = some_function_that_takes_arguments( 'a', 'b', 'c', 'd', 'e', 'f', ) Good programming • Long lines with open('/path/to/some/file/you/want/to/read') as file_1, \ open('/path/to/some/file/being/written', 'w') as file_2: file_2.write(file_1.read()) class Rectangle(Blob): def __init__(self, width, height, color='black', emphasis=None, highlight=0): if (width == 0 and height == 0 and color == 'red' and emphasis == 'strong' or highlight > 100): raise ValueError("sorry, you lose") if width == 0 and height == 0 and (color == 'red' or emphasis is None): raise ValueError("I don't think so -- values are %s, %s" % (width, height)) Blob.__init__(self, width, height, color, emphasis, highlight) Good programming • White space Yes: spam(ham[1], {eggs: 2}) No: spam( ham[ 1 ], { eggs: 2 } ) Yes: if x == 4: print x, y; x, y = y, x No: if x == 4 : print x , y ; x , y = y , x Yes: i = i + 1 submitted += 1 x = x*2 - 1 hypot2 = x*x + y*y c = (a+b) * (a-b) No: i=i+1 submitted +=1 x = x * 2 - 1 hypot2 = x * x + y * y c = (a + b) * (a - b) Introduction to language - help • Powerful help tools • Every object, function, module, .., can be inspected >>> help(math) >>> help(math.cos) >>> a = [1, 2, 3] >>> help(a) Introduction to language - exceptions Languages that don’t have exception handling built in (e.g. FORTRAN, C) tend to have code that is sprinkled with code like this: ratio = 0.0; if (x == 0) { printf("Divisor = 0"); } else { ratio = y/x; } In Python (and C++, Java and other more modern languages), an error will throw an exception, which you can then handle. So the equivalent code in Python would look like... Introduction to language - exceptions Try-except x = 0.0 try: ratio = y/x except ZeroDivisionError: print 'Divisor = 0' The try/except syntax has the advantage that what you want to do appears first, you don’t have to read past a lot of error trapping code to find out what a particular block of code is doing try: [do some processing] except SomeError: [respond to this particular error condition] raise Some(other)Error # now let something else handle the error BaseException | +-- RuntimeError +-- SystemExit | | +-- NotImplementedError +-- KeyboardInterrupt | +-- SyntaxError +-- GeneratorExit | | +-- IndentationError +-- Exception | | +-- TabError +-- StopIteration | +-- SystemError +-- StandardError | +-- TypeError Try-except | +-- BufferError | +-- ValueError import sys | +-- ArithmeticError | +-- UnicodeError try: | | +-- FloatingPointError | +-- UnicodeDecodeError untrusted.execute() | | +-- OverflowError | +-- UnicodeEncodeError except: # catch *all* exceptions | | +-- ZeroDivisionError | +-- UnicodeTranslateError e = sys.exc_info()[0] | +-- AssertionError +-- Warning write_to_page( "<p>Error: %s</p>" % e ) | +-- AttributeError +-- DeprecationWarning | +-- EnvironmentError +-- PendingDeprecationWarning | | +-- IOError +-- RuntimeWarning import sys | | +-- OSError +-- SyntaxWarning | | +-- WindowsError (Windows) +-- UserWarning try: | | +-- VMSError (VMS) +-- FutureWarning f = open('myfile.txt') | +-- EOFError +-- ImportWarning s = f.readline() | +-- ImportError +-- UnicodeWarning i = int(s.strip()) | +-- LookupError +-- BytesWarning except IOError as e: | | +-- IndexError print "I/O error({0}): {1}".format(e.errno, e.strerror) | | +-- KeyError except ValueError: | +-- MemoryError print "Could not convert data to an integer." | +-- NameError except: | | +-- UnboundLocalError print "Unexpected error:", sys.exc_info()[0] | +-- ReferenceError raise Introduction to language - exceptions Introduction to language End