Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Python Fundamentals by Chris Seddon Copyright ©2000-14 CRS Enterprises Ltd 1 Python Fundamentals . 1 Introduction to Python 2.Control Structures 3.Basic Data Types 4.Advanced Data Types 5.Dictionaries 6.Functions 7.Exception Handling 8.Classes and Objects 9. Files 10.Larger Programs 11.Inheritance 12.Further Topics 13.Pattern Matching 14.Unit Test Copyright ©2000-14 CRS Enterprises Ltd 3 Chapter 1 1 Copyright ©2000-14 CRS Enterprises Ltd 5 Introduction to Python IronPython Copyright ©2000-14 CRS Enterprises Ltd 6 What is Python? Python is a scripting language unlike C++, C# and Java easy to learn no compile step can be run a line at a time inside an interpreter supports dynamic execution of source (you can type in code at run time) Supports both Object Oriented and functional styles of programming often described as an agile language capable of performing a wide variety of tasks ideal for rapid prototyping often used as a plug-in to a C++ or Java system Copyright ©2000-14 CRS Enterprises Ltd 7 Advantages of Python Python is best used to develop small programs and scripts simple programs can be created very quickly Python can be used for large-scale programming projects sophisticated module and packaging scheme extensive object oriented support Jython has access to all Java libraries Python was designed to be an object oriented language from the start more simplified and natural coding style than Perl, Rexx and VBScript highly portable Copyright ©2000-14 CRS Enterprises Ltd 8 What is Jython? An implementation of Python fully integrated with the Java Virtual Machine runs on any JVM unlike a Python program including Windows, Mac OS, most UNIX, all Linux systems, and all IBM systems highly portable because of the connection with Java Jython currently supports the Python syntax at level 2.5 Jython Libraries uses Java libraries because of the JVM NOT standard Python libraries can be a problem sometimes Copyright ©2000-14 CRS Enterprises Ltd 9 Everything is Interpreted Python is an interpreted language no pre-compile step as in Java and C++ each time Python code is run it is interpreted afresh code changes can be very quickly made and tested code can also be entered interactively can dynamically construct Python code, in the form of a string and execute it directly myPython.py myJava.java myJava.class Target Hardware Copyright ©2000-14 CRS Enterprises Ltd JVM 10 Performance Python is interpreted much slower than a compiled language such as C/C++ increased design and coding flexibility more than makes up for performance loss Python libraries usually written in C/C++ a large proportion of the Python library is written in C/C++ as is the interpreter itself hence high performance Python has modules to measure performance profile, cProfile Copyright ©2000-14 CRS Enterprises Ltd 11 Invoking Python Use the Command-Line Interpreter code is entered one line at a time see the results immediately ideal way to learn Python Use Python source files complied by the Python interpreter source files can be combined using modules for larger applications Python plug-in for Eclipse is often a good choice PyDev is very mature Copyright ©2000-14 CRS Enterprises Ltd 12 A "Hello World" Example The Hello World example is a trivial one liner in Python; you don’t even require a semi-colon! print "Hello World!" Copyright ©2000-14 CRS Enterprises Ltd 13 Further Example The Hello World example is a trivial one liner in Python; you don’t even require a semi-colon! # this is a comment x = 100 y = 200 if x + y < 500: print "sum is less than 500" colon indent Copyright ©2000-14 CRS Enterprises Ltd 14 Chapter 2 2 Copyright ©2000-14 CRS Enterprises Ltd 17 Control Structures Statements if for while Copyright ©2000-14 CRS Enterprises Ltd 18 if Statements x = int(raw_input("Please enter an integer: ")) if x < 0: print 'Negative' Please enter an integer: -5 Negative Copyright ©2000-14 CRS Enterprises Ltd 19 if Statements x = int(raw_input("Please enter a positive integer: ")) if x > 0: print 'x is positive' print 'the square of x is', x * x print 'the cube of x is', x * x * x print 'End of if-statement' Please enter a positive integer: 66 x is positive the square of x is 4356 the cube of x is 287496 End of if-statement Copyright ©2000-14 CRS Enterprises Ltd 20 if-else Statements x = int(raw_input("Please enter an integer: ")) if x < 0: print 'Negative' else: print 'Not negative' Please enter an integer: 5 Not negative Please enter an integer: -5 Negative Copyright ©2000-14 CRS Enterprises Ltd 21 if-elif-else Statements x = int(raw_input("Please enter an integer: ")) if x < 0: print 'Negative' elif x == 0: print 'Zero' elif x == 1: print 'One' else: print 'Greater than one' Copyright ©2000-14 CRS Enterprises Ltd Please enter an integer: -3 Negative Please enter an integer: 0 Zero Please enter an integer: 1 One Please enter an integer: 7 Greater than one 22 Conditional if Statements x = 100 result = (-1 if x < 0 else 1) print result x = -200 result = (-1 if x < 0 else 1) print result 1 -1 Copyright ©2000-14 CRS Enterprises Ltd 23 for Statements for x in (10,17,24,31,38,45,52,59,66,73,80,87,94): print x, print for x in range(10,100,7): print x, 10 17 24 31 38 45 52 59 66 73 80 87 94 10 17 24 31 38 45 52 59 66 73 80 87 94 Copyright ©2000-14 CRS Enterprises Ltd 24 for-else Statements for x in (1,2,3,4,5,6): print x, else: print "only get here if all iterations succeed ..." for x in (1,2,3,4,5,6): print x, if x > 3: break else: print "only get here if all iterations succeed ..." 1 2 3 4 5 6 only get here if all iterations succeed ... 1234 Copyright ©2000-14 CRS Enterprises Ltd 25 Using range use range to iterate a fixed number of times for x in range(1,10): print x, 123456789 Copyright ©2000-14 CRS Enterprises Ltd 26 while Statements formula = 0 x=0 while formula < 1000: x=x+1 formula = 2*x*(x + 1) print x, formula Copyright ©2000-14 CRS Enterprises Ltd 1 4 2 12 3 24 4 40 5 60 6 84 7 112 8 144 9 180 10 220 11 264 12 312 13 364 14 420 15 480 16 544 17 612 18 684 19 760 20 840 21 924 22 1012 27 Chapter 3 3 Copyright ©2000-14 CRS Enterprises Ltd 29 Basic Data Types Basic Types int long boolean float complex string Copyright ©2000-14 CRS Enterprises Ltd 30 Data Types Everything is an object including all types discussed in this chapter full documentation for the Java types is online Several types are immutable strings, tuples Sometimes objects behave as though immutable if you attempt to modify a number, Python simply creates a new object and marks the old object ready for garbage collection could lead to excessive delays during the garbage collection cycle. Copyright ©2000-14 CRS Enterprises Ltd 31 Built in Types int C long includes Booleans hex and octal numbers available boolean True, False, and, or float C double type (13 sig. fig.) long unlimited precision e.g. 10000000000000000000000000 complex real and imaginary parts are each implemented using Java double e.g. (5.0+3.1j) Copyright ©2000-14 CRS Enterprises Ltd 32 Integers Limited precision decimals, octal and hexadecimal # integers x = 100 x += 1 print type(x) print x x = 053 print x <type 'int'> 101 43 255 x = 0xFF print x Copyright ©2000-14 CRS Enterprises Ltd 33 Booleans Values True, False Operators and, or x = True y = False z = x or y print z True z = x and y print z print type(z) False <type 'bool'> Copyright ©2000-14 CRS Enterprises Ltd 34 Floating Point 13 significant figures on 64 bit implementation no exact representation # floating point x = 1e4 + 0.1e-4 format = "%32.20g" print type(x) print (format % x) <type 'float'> 10000.000009999999747 Copyright ©2000-14 CRS Enterprises Ltd 35 Complex Numbers floating types real and imaginary parts can be extracted separately x = (+2.5-3.4j) - (-1.4+1.0j) print type(x) print x print x.real print x.imag Copyright ©2000-14 CRS Enterprises Ltd <type 'complex'> (3.9-4.4j) 3.9 -4.4 36 Integers are Immutable x is really an object reference (pointer) id(x) refers to the object at the end of the pointer x can change, but integer it points to is immutable x just points to a different object the original object gets garbage collected x = 100 print id(x) 10053412 x=x+1 print id(x) 10053400 Copyright ©2000-14 CRS Enterprises Ltd 37 Strings ... immutable single or double quotes triple quoting for multi-line strings x = 'hello' y = "from" z = """the planet earth""" print type(x) print x, y, z <type 'str'> hello from the planet earth HELLO FROM THE PLANET EARTH phrase = x + " " + y + " " + z print phrase.upper() Copyright ©2000-14 CRS Enterprises Ltd 38 ... Strings Many string manipulation methods available original string is unchanged new string returned s = "---abc:XYZ:123---" t = s.lower() t = s.lstrip("-") t = s.replace(":","@") t = s.rstrip("-") t = s.split(":") t = s.strip("-") t = s.swapcase() t = s.upper() Copyright ©2000-14 CRS Enterprises Ltd ---abc:xyz:123--abc:XYZ:123-----abc@XYZ@123-----abc:XYZ:123 ['---abc', 'XYZ', '123---'] abc:XYZ:123 ---ABC:xyz:123-----ABC:XYZ:123--- 39 ... Strings More string methods ... count(sub) find(sub) number of occurrences of substring index in the string where substring is found isalnum() isalpha() true if string is alphanumeric true if string is alphabetic isdigit() true if string is all digits join(seq) partition(sep) concatenate all the strings in the sequence split the string at the first occurrence of sep and return a 3tuple split(sep) return a list of the words in the string using sep as the delimiter Copyright ©2000-14 CRS Enterprises Ltd 40 Chapter 4 4 Copyright ©2000-14 CRS Enterprises Ltd 43 Advanced Data Types Sequence Types list (mutable) tuple (immutable) set use [ ] use ( ) no duplicates Dictionary Types dict (mutable) use { } Copyright ©2000-14 CRS Enterprises Ltd 44 List ... mutable can be nested x1 = [ ] x2 = [1] x3 = [1,2,3] x4 = [1, 'mixed', 2, 'list'] x5 = [[1,2],[3,4]] print type(x1) print x1, "-----", len(x1) print x2, "-----", len(x2) print x3, "-----", len(x3) print x4, "-----", len(x4) print x5, "-----", len(x5) Copyright ©2000-14 CRS Enterprises Ltd <type 'list'> [] [1] [1, 2, 3] [1, 'mixed', 2, 'list'] [[1, 2], [3, 4]] ----- 0 ----- 1 ----- 3 ----- 4 ----- 2 45 ... List Lists can be extended with extend or append Elements can be modified object reference gets changed Can contain immutable items such as tuples list1 = [[1,2],[3,4]] # notation for accessing lists print list1 print list1[1] print list1[1][0] # append and extend are equivalent list2 = [10, 20, 30] list = [ ] list.extend(list1) list.append(list2) print list # modifying lists list1[1][0] = 99 print list1[1][0] # lists can contain tuples list3 = [(1,2), (3,4), (5,6)] print list3 Copyright ©2000-14 CRS Enterprises Ltd 46 Tuple immutable can be nested note syntax for a single item tuple x1 = () x2 = (1,) x3 = (1,2,3) x4 = (1, "mixed", 2, "tuple") x5 = ((1,2),(3,4)) print type(x1) print x1, "-----", len(x1) print x2, "-----", len(x2) print x3, "-----", len(x3) print x4, "-----", len(x4) print x5, "-----", len(x5) Copyright ©2000-14 CRS Enterprises Ltd <type 'tuple'> () (1,) (1, 2, 3) (1, 'mixed', 2, 'tuple') ((1, 2), (3, 4)) ----- 0 ----- 1 ----- 3 ----- 4 ----- 2 47 Accessing Lists and Tuples only lists can be modified tuples are immutable mylist = [10, 20, 30] mytuple = (10, 20, 30) y = mytuple[0] y = mytuple[1] y = mytuple[2] x = mylist[0] x = mylist[1] x = mylist[2] mylist[1] = 99 mylist.append(40) print mylist Copyright ©2000-14 CRS Enterprises Ltd [10, 99, 30, 40] 48 Casting between Lists and Tuples use a cast to convert tuple( ... ) list( ...) theList = [2, 3, 5, 7, 11, 13, 17] myTuple = tuple(theList) myList = list(myTuple) print myTuple print myList Copyright ©2000-14 CRS Enterprises Ltd (2, 3, 5, 7, 11, 13, 17) [2, 3, 5, 7, 11, 13, 17] 49 Slices Sequences support slicing selects a range of elements (-1 represents the last element) x[1:3] selects the second through third elements of x the end index is always one past the selection assignment slicing replaces multiple elements x[3:5] = (5,4) colors = ["red", "blue", "green", "white", "black"] print colors[1] print colors[1:3] print colors[1:] print colors[-3:-1] print colors[4:1:-1] colors[2:4] = ("purple", "cyan") print colors[0:]; Copyright ©2000-14 CRS Enterprises Ltd blue ['blue', 'green'] ['blue', 'green', 'white', 'black'] ['green', 'white'] ['black', 'white', 'green'] ['red', 'blue', 'purple', 'cyan', 'black'] 50 Set and FrozenSet unordered collections of unique elements Set (mutable) FrozenSet (immutable) myset = set(("Monday", "Tuesday")) myset.add("Wednesday") myset.add("Thursday") myset.add("Friday") print myset if "Wednesday" in myset: print "member" myset.remove("Wednesday") if "Wednesday" not in myset: print "not a member" Copyright ©2000-14 CRS Enterprises Ltd set(['Friday', 'Tuesday', 'Thursday', 'Wednesday', 'Monday']) member not a member 51 Set and FrozenSet Set supports mathematical operations union, intersection and symmetric difference sequence1 = 1, 3, 5, 7, 5, 4, 3, 2, 1 sequence2 = 2, 4, 6, 8, 6, 4, 3, 2, 1 set1 = set(sequence1) set2 = set(sequence2) print(set1) set([1, 2, 3, 4, 5, 7]) print(set2) set([1, 2, 3, 4, 6, 8]) unionSet = set1.union(set2) intersectionSet = set1.intersection(set2) differenceSet = set1.symmetric_difference(set2) print(unionSet) set([1, 2, 3, 4, 5, 6, 7, 8]) print(intersectionSet) set([1, 2, 3, 4]) print(differenceSet) set([5, 6, 7, 8]) Copyright ©2000-14 CRS Enterprises Ltd 52 Not Defined special type NoneType x = 120 print type(x) print x x = None # not defined print type(x) print x <type 'int'> 120 <type 'NoneType'> None 240 if (x == None): x = 240 print x Copyright ©2000-14 CRS Enterprises Ltd 53 Chapter 5 5 Copyright ©2000-14 CRS Enterprises Ltd 55 Dictionaries keys and values inserting, updating and deleting common methods Copyright ©2000-14 CRS Enterprises Ltd 56 Dictionary like a database table also called hash, associative array key:value pairs keys usually a string keys must be immutable very efficient lookups empty = { } months = {"Jan":1, "Feb":2, "May":5, "Dec":12} seasons = {"Spring":("Mar","Apr","May"), "Summer":("Jun","Jul","Aug")} print type(empty) print months["Dec"] print seasons["Summer"] Copyright ©2000-14 CRS Enterprises Ltd <type 'dict'> 12 ('Jun', 'Jul', 'Aug') 57 Working with Dictionaries Dictionaries are mutable modify existing entries add new entries Key Order is indeterminate because of hashing algorithm salary = { "zak": 34000, "sara": 27000, "pedro": 52000, "jo": 12500, "zoe": 66000 } print salary["pedro"] salary["jo"] = 15000; # modify existing salary["peter"] = 35000 # add new entry Copyright ©2000-14 CRS Enterprises Ltd 58 Initialization Use { } or constructor salary1 = { "zak": 34000, "sara": 27000, "pedro": 52000, "kilas": 12500, "zoe": 66000 } salary2 = dict( zak = 34000, sara = 27000, pedro = 52000, kilas = 12500, zoe = 66000) Copyright ©2000-14 CRS Enterprises Ltd 59 Inserting or Updating New elements ... are added salary["sara"] = 28000 Existing elements ... are updated salary["sara"] = 29000 Copyright ©2000-14 CRS Enterprises Ltd 60 Removing Keys Use del statement del salary["zak"] or Use pop salary.pop("zak") Copyright ©2000-14 CRS Enterprises Ltd 61 Removing Values Assign key to None previous value gets garbage collected salary["sara"] = None Copyright ©2000-14 CRS Enterprises Ltd 62 Common Functions ... Extract all the keys, and all the values # create list of keys theKeys = salary.keys() # create list of values theValues = salary.values() Copyright ©2000-14 CRS Enterprises Ltd 63 ... Common Functions Work with keys, values or both # print all the keys for key in salary.iterkeys(): print key, print # print all the values for value in salary.itervalues(): print value, print # print all <key,value> pairs for key, value in salary.iteritems(): print key, value Copyright ©2000-14 CRS Enterprises Ltd 64 Chapter 6 6 Copyright ©2000-14 CRS Enterprises Ltd 67 Functions Simple functions Passing parameters Returning multiple results Pass by value Working with lists Pass by object reference Object identity Copyright ©2000-14 CRS Enterprises Ltd 68 Simple Functions def square(n): print n * n square(5) square(6) square(7) 25 36 49 Copyright ©2000-14 CRS Enterprises Ltd 69 return Statements def average(a, b): return (a + b)/2.0 x = average(5, 8) print x x = average(5.5, 7.7) print x print average(10.5, 12.5) 6.5 6.6 11.5 Copyright ©2000-14 CRS Enterprises Ltd 70 A swap Function def swap(a,b): return b,a x = 100 y = 200 [x,y] = swap(x,y) print x, y 200 100 Copyright ©2000-14 CRS Enterprises Ltd 71 How not to Swap def no_swap(a,b): temp = a a=b b = temp x = 100 y = 200 no_swap(x,y) print x, y 100 200 Copyright ©2000-14 CRS Enterprises Ltd 72 Object Identity def readIt(a): print a,"id3 =",id(a) def modifyIt(a): a=a+1 print a,"id4 =",id(a) 100 id1 = 12160993 101 id2 = 9774375 101 id3 = 9774375 102 id4 = 28991818 x = 100 print x,"id1 =",id(x) x=x+1 print x,"id2 =",id(x) readIt(x) modifyIt(x) Copyright ©2000-14 CRS Enterprises Ltd 73 Object Identity with Lists list1 = [2, 3, 5, 7, 11] list2 = [2, 4, 6, 8, 10] list3 = [2, 4, 6, 8, 10] print "list1 id =", id(list1) print "list2 id =", id(list2) print "list3 id =", id(list3) list1.append(13) print "list1 id =", id(list1) list1 id = 9774375 list2 id = 28991818 list3 id = 21579068 list1 id = 9774375 Copyright ©2000-14 CRS Enterprises Ltd 74 Pass by Object Reference def modifyList(mylist): del mylist[0] print id(mylist),mylist theList = [2, 3, 5, 7, 11] print id(theList), theList modifyList(theList) print id(theList), theList 12160993 [2, 3, 5, 7, 11] 12160993 [3, 5, 7, 11] 12160993 [3, 5, 7, 11] Copyright ©2000-14 CRS Enterprises Ltd 75 Swapping Lists def swap(list): list[0],list[1] = list[1],list[0] mylist = [100,200] swap(mylist) print mylist [200, 100] Copyright ©2000-14 CRS Enterprises Ltd 76 Returning Lists def makeList(start,end): mylist = range(start, end) mylist.insert(0, 10) mylist.append(99) return mylist list1 = makeList(15, 25) list2 = makeList(18, 21) print list1 print list2 [10, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 99] [10, 18, 19, 20, 99] Copyright ©2000-14 CRS Enterprises Ltd 77 Function Aliases def fib(n): a, b = 0, 1 while b < n: print b, a, b = b, a+b print fib(15000) f = fib f(100) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 1 1 2 3 5 8 13 21 34 55 89 Copyright ©2000-14 CRS Enterprises Ltd 78 Default Parameter Values def Display(a, b=10, c=100): print ("a=%6.1f " % a), ("b=%6.1f " % b), ("c=%6.1f" % c) Display(19, 6.2, 4.8) Display(17) Display(17, 21) Display(17, c=0) a= a= a= a= Copyright ©2000-14 CRS Enterprises Ltd 19.0 17.0 17.0 17.0 b= b= b= b= 6.2 10.0 21.0 10.0 c= 4.8 c= 100.0 c= 100.0 c= 0.0 79 Lambda Functions sum = lambda x, y: x + y print sum(1,2) print sum(5,9) print sum(10,20) 3 14 30 Copyright ©2000-14 CRS Enterprises Ltd 80 Passing Tuples and Lists def f(*args): print 'args:', args a = (3,4,7,8) b = [3,4,7,8] args: (1, 3, 4, 7, 8, 9) args: (1, (3, 4, 7, 8), 9) args: (1, [3, 4, 7, 8], 9) args: (1, 3, 4, 7, 8) args: (1, 3, 4, 7, 8) f(1,3,4,7,8,9) # pass multiple args f(1,a,9) # pass int, tuple, int f(1,b,9) # pass int, list, int f(1,*a) # treat tuple as multiple args f(1,*b) # treat list as multiple args Copyright ©2000-14 CRS Enterprises Ltd 81 Passing Named Parameters def f(x,y,**params): print 'x,y:', x, y print 'params:', params f(13,7, Jan=1, Feb=2, May=5, Dec=12) x,y: 13 7 params: {'Dec': 12, 'May': 5, 'Jan': 1, 'Feb': 2} Copyright ©2000-14 CRS Enterprises Ltd 82 Stub Functions def myStub(x, y): pass myStub(5,6) myStub(1,10) myStub(0,7) Copyright ©2000-14 CRS Enterprises Ltd 83 Chapter 7 7 Copyright ©2000-14 CRS Enterprises Ltd 85 Exception Handling Keywords try except finally raise assert Copyright ©2000-14 CRS Enterprises Ltd 86 try-except Statements array = [1,2,3,4,5,6] exception thrown here try: for x in array: print x, array[x] exception type print "Exiting try block" except IndexError,target: print "... entering except block" print target this is never executed object reference 23 34 45 56 6 ... entering except block list index out of range Copyright ©2000-14 CRS Enterprises Ltd 87 try-except-else Statements from math import sqrt x = int(raw_input("Enter positive integer: ")) try: root = sqrt(x) except: print "... entering except block" else: print "... entering else block" print root exception occurs no exception Enter positive integer: 25 ... entering else block 5.0 Enter positive integer: -25 ... entering except block Copyright ©2000-14 CRS Enterprises Ltd 88 try-finally Statements array = [1,2,3,4,5,6] 1 2 3 4 5 6 ... entering finally block 3 5 ... entering finally block IndexError: list index out of range try: for x in array: print array[x - 1], finally: print "... entering finally block" guaranteed to be called even if exception occurs try: for x in array: print array[x * 2], finally: print "... entering finally block" Copyright ©2000-14 CRS Enterprises Ltd 89 raise Statements array = [1,2,3,-4,5,6] try: exception type for x in array: if x < 0: raise ValueError, "array index is negative!" print x, object reference except ValueError, value: print print "... entering except block: " + str(value) 123 ... entering except block: array index is negative! Copyright ©2000-14 CRS Enterprises Ltd 90 Unified try except finally In Python 2.5+ you can combine finally and except not allowed in previous versions try: block-1 ... except Exception1: handler-1 ... except Exception2: handler-2 ... else: else-block finally: final-block Copyright ©2000-14 CRS Enterprises Ltd 91 Nested Exceptions def f1(): print "Entering f1" f2() print "Leaving f1" never executed def f2(): print "Entering f2" f3() print "Leaving f2" regarded as part of the try block Entering f1 Entering f2 Entering f3 Some exception def f3(): print "Entering f3" raise Exception("Some exception") print "Leaving f3" try: f1() except Exception, reason: print reason Copyright ©2000-14 CRS Enterprises Ltd 92 Standard Exceptions Exception StopIteration StandardError BufferError ArithmeticError FloatingPointErro OverflowError ZeroDivisionError AssertionError AttributeError EnvironmentError IOError OSError EOFError ImportError LookupError IndexError KeyError Copyright ©2000-14 CRS Enterprises Ltd MemoryError NameError UnboundLocalError ReferenceError RuntimeError NotImplementedError SyntaxError IndentationError TabError SystemError TypeError ValueError UnicodeError UnicodeDecodeError UnicodeEncodeError UnicodeTranslateError 93 User Defined Exceptions Always subclass Exception class MyError(Exception): def __init__(self, value): self.value = value My exception occurred, value: 4 try: raise MyError(2*2) except MyError as e: print 'My exception occurred, value:', e.value Copyright ©2000-14 CRS Enterprises Ltd 94 assert Statements def CalculateQuartile(percent): assert type(percent).__name__ == 'int' assert percent >= 0 and percent <= 100 quartile = 4 if percent > 25: print CalculateQuartile(34) quartile = 3 print CalculateQuartile(104) if percent > 50: quartile = 2 if percent > 75: 2 quartile = 1 assert percent >= 0 and percent <= 100 return quartile AssertionError Copyright ©2000-14 CRS Enterprises Ltd 95 Chapter 8 8 Copyright ©2000-14 CRS Enterprises Ltd 97 Classes and Objects Classes what is a class what is an object Methods defining calling Attributes for objects for classes Copyright ©2000-14 CRS Enterprises Ltd 98 The Object Model Object-oriented programming modelling real-world objects model described by classes model implemented by creating objects Copyright ©2000-14 CRS Enterprises Ltd 99 Classes A class defines a new data type its operations its state Type Yacht { Tack Operations DropAnchor bearing speed Copyright ©2000-14 CRS Enterprises Ltd } Attributes 100 Classes methods are functions attributes are object references reference to self operations methods class Yacht: def __init__(self, bearing, speed): self.bearing = bearing self.speed = speed attributes def Display(self): print self.bearing, self.speed Copyright ©2000-14 CRS Enterprises Ltd 101 Objects A class is a blueprint for building objects An object is an instance of a class keyword self refers to this instance class Yacht: def __init__(self, bearing, speed): self.bearing = bearing self.speed = speed def Display(self): print self.bearing, self.speed Object 1 Object 2 bearing = 40 speed = 1.7 bearing = 30 speed = 1.3 Copyright ©2000-14 CRS Enterprises Ltd 102 Creating Objects Use the classname to create a new object returns an object reference the object is not directly accessible Object destroyed by the VM when no references exist object reference Copyright ©2000-14 CRS Enterprises Ltd oceanis1 = Yacht() oceanis2 = Yacht() mirror1 = Yacht() mirror2 = Yacht() 103 Initializing Objects Classes can define an __init__ method method often takes parameters defines how object will be initialized only 1 initializer allowed mirror1 = Yacht(25, 1.2) mirror1 Copyright ©2000-14 CRS Enterprises Ltd def __init__(self, bearing, speed): self.bearing = bearing self.speed = speed bearing = 25 speed = 1.2 104 Initializing Objects class Yacht: def __init__(self, bearing, speed): self.bearing = bearing self.speed = speed def Display(self): print self.bearing, self.speed oceanis1 = Yacht(25, 1.2) oceanis2 = Yacht(35, 6.0) mirror1 = Yacht(90, 3.5) mirror2 = Yacht(220, 1.6) 25 1.2 35 6.0 90 3.5 220 1.6 oceanis1.Display() oceanis2.Display() mirror1.Display() mirror2.Display() Copyright ©2000-14 CRS Enterprises Ltd 105 Assigning References Assigning references both point to the same object mirror1 bearing = 25 speed = 1.2 mirror2 mirror1 = Yacht(25, 1.2) mirror2 = mirror1 Copyright ©2000-14 CRS Enterprises Ltd 106 Attributes Class Attributes shared by all objects in a class Object Attributes unique to each object Avoid name clashes object attribute hides class attribute of the same name Copyright ©2000-14 CRS Enterprises Ltd 107 Object Attributes Object attributes can be defined on the fly can apply to different objects Object b1 has height width color Object b2 has height width Use pass to define a empty class useful for trying things out Copyright ©2000-14 CRS Enterprises Ltd class Box: pass b1 = Box( ) b2 = Box( ) b1.height = 100 b1.width = 50 b1.color = "red" b2.height = 100 b2.width = 50 108 Class Attributes Shared by all objects in class class attribute class Point: count = 0 object attribute def __init__(self, x = 0, y = 0): self.x = x self.y = y Point.count = Point.count + 1 def WhereAmI(self): print "Point(%i) is at %i,%i" % (id(self), self.x, self.y) normal method static(class) method def MoveBy(self, dx, dy): self.x += dx self.y += dy def HowManyPoints(self): print "There are %i Point object(s)\n" % Point.count Copyright ©2000-14 CRS Enterprises Ltd 109 Manipulating Objects p1 = Point(5,7) p1.WhereAmI() p1.MoveBy(1,1) p1.WhereAmI() p1.HowManyPoints() p2 = Point(15,17) p2.WhereAmI() p2.MoveBy(1,10) p2.WhereAmI() p1.HowManyPoints() p3 = Point(25,27) p3.WhereAmI() p3.MoveBy(1,100) p3.WhereAmI() p1.HowManyPoints() Copyright ©2000-14 CRS Enterprises Ltd class Point: count = 0 def __init__(self, x = 0, y = 0): self.x = x self.y = y Point.count = Point.count + 1 def WhereAmI(self): print "Point(%i) is at ... def MoveBy(self, dx, dy): self.x += dx self.y += dy def HowManyPoints(self): print "There are ... 110 Output from Example Note each object has a unique identifier print id(p1) print id(p2) print id(p3) Note the effect of calling p1.HowManyPoints() Point(23107068) is at 5,7 Point(23107068) is at 6,8 There are 1 Point object(s) Point(24318772) is at 15,17 Point(24318772) is at 16,27 There are 2 Point object(s) Point(27787651) is at 25,27 Point(27787651) is at 26,127 There are 3 Point object(s) Copyright ©2000-14 CRS Enterprises Ltd 111 Chapter 9 9 Copyright ©2000-14 CRS Enterprises Ltd 113 Files Opening and closing Reading and writing Modes read only read-write append Iterating through Random Access seek Copyright ©2000-14 CRS Enterprises Ltd 114 File Objects open creates a file object close destroys a file object myFile = open('myfile.txt', 'w') myFile.close() Copyright ©2000-14 CRS Enterprises Ltd 115 Iterating through a File Use for-in statement to process every line loop terminates on end of file f = open("hello.txt") for line in f: print line Copyright ©2000-14 CRS Enterprises Ltd 116 Using with Statement with statement automatic clean up avoid forgetting to close a file generated code inner try block will always close but might throw an IOError generated code try: f = open("data/hello.txt", "r") try: for line in f: print line, finally: f.close() except IOError,e: print e try: with open("data/hello.txt", "r") as f: for line in f: print line, except IOError,e: print e Copyright ©2000-14 CRS Enterprises Ltd 117 Coping with Errors If file I/O fails Error obect thrown belongs to IOError class try: f = open("data/unknown.txt", "r+t") except IOError,error: print "File open failed!" error object print error error class Copyright ©2000-14 CRS Enterprises Ltd 118 Read Methods Simple to read from files f = open('myfile.txt', 'w') data = f.read() f.close() read entire file f = open('myfile.txt', 'w') data = f.read(100) f.close() f = open('myfile.txt', 'r') f.readline() f.readline() f.readline() f.close() read a line at a time (empty string returned on EOF) read 100 bytes from file Copyright ©2000-14 CRS Enterprises Ltd 119 Write Methods Simple to write to files f = open("data/out1.txt", "w") f.write("line 1\nline 2\n") f.close() write a string sequence = ("line 1\n", "line 2\n", "line 3\n", "line 4\n") f = open("data/out2.txt", "w") f.writelines(sequence) f.close() write a sequence of lines Copyright ©2000-14 CRS Enterprises Ltd 120 File Modes read only use "r" read and write use "r+" or "w+" to empty file on opening write only use "w" file will be empty on opening appending use "a" binary use "b" for binary and "t" for text (default) random access choose appropriate mode and then use seek() Copyright ©2000-14 CRS Enterprises Ltd 121 Writing Binary Data Open file with mode 'b' myFile = open('data/myfile2.bin', 'wb') myFile.write("\x5F\x9D\x3E"); myFile.close() Copyright ©2000-14 CRS Enterprises Ltd 122 Reading Binary Data Use ord() and hex(ord()) for conversions myFile = open('data/myfile2.bin', 'rb') # read bytes ch1 = myFile.read(1) # read 1 byte ch2 = myFile.read(1) ch3 = myFile.read(1) # convert to ascii (decimal) d1 = ord(ch1) d2 = ord(ch2) d3 = ord(ch3) # convert to ascii (hex) h1 = hex(ord(ch1)) h2 = hex(ord(ch2)) h3 = hex(ord(ch3)) myFile.close() Copyright ©2000-14 CRS Enterprises Ltd 123 Random Access seek(offset, whence) whence = 0 whence = 1 whence = 2 => from start of file => from current position => from end of file myFile = open('myfile.txt', 'w') myFile.seek(40, 0) myFile.write("ABCDEFGH"); myFile.seek(140, 0) myFile.write("ABCDEFGH"); myFile.seek(240, 0) myFile.write("ABCDEFGH"); myFile.close() Copyright ©2000-14 CRS Enterprises Ltd 124 Reading a File into a Dictionary You can read an entire file into a Dictionary and then perform lookups stdcodes = {} f = open("codes.txt", "r+t") read a file line by line, splitting each line and then adding to dictionary for line in f: [code, place] = line.rstrip().split(' ', 1) stdcodes[place] = code now try searching the dictionary placeRequested = raw_input("Enter place: ") try: print "The code for " + placeRequested + \ " is " + stdcodes[placeRequested] Town: Washington except KeyError: The code for Washington is 0191 print "code not found" Copyright ©2000-14 CRS Enterprises Ltd 125 Sorting a File stdcodes = {} f = open("codes.txt", "r+t") read a file line by line, splitting each line and then adding to dictionary for line in f: [code, place] = line.rstrip().split(' ', 1) stdcodes[place] = code list = [ ] list = stdcodes.keys() list.sort() for place in list: print place, stdcodes[place] Copyright ©2000-14 CRS Enterprises Ltd extract the keys into an array then sort the array now step through the sorted list looking up each entry in the original dictionary 126 Chapter 10 10 Copyright ©2000-14 CRS Enterprises Ltd 129 Larger Programs Modules and Packages Importing Symbol Tables Installing Libraries Copyright ©2000-14 CRS Enterprises Ltd 130 Modules and Packages Programs can be organized into modules and packages many modules are available in the Python and Java libraries Modules may be Python code files but can be written in other languages such as C/C++ Packages collection of modules grouped using a common package name helps resolve namespace conflicts A package is defined by creating a directory with the same name as the package place modules in this directory can be extended to include sub-packages within sub-directories Copyright ©2000-14 CRS Enterprises Ltd 131 What is a Module Importing a file executes all the code in that file often just defines functions import myfunctions myfunctions.f1() myfunctions.f2() myfunctions.f3() myfunctions.f4() myfunctions.py def f1(): pass def f2(): pass def f3(): pass def f4(): pass Copyright ©2000-14 CRS Enterprises Ltd 132 Module Test Code Importing a file ... causes all code to executed but what about test code? Wrap all test code ... inside a __name__ test __name__ is only set to __main__ if we are the main program code will not be executed via an import Copyright ©2000-14 CRS Enterprises Ltd def f1(): def f2(): def f3(): def f4(): pass pass pass pass if __name__ == "__main__": f1() f2() f3() f4() 133 Importing 4 ways to import mypackage mysubpackage import mypackage.mysubpackage.MyClass x1 = mypackage.mysubpackage.MyClass() x1.f1() from mypackage import mysubpackage x2 = mysubpackage.MyClass() x2.f2() public class MyClass { public MyClass() { ... } public void f1() { ... } public void f2() { ... } public void f3() { ... } public void f4() { ... } } import mypackage.mysubpackage.MyClass as theClass x3 = theClass() x3.f3() from mypackage.mysubpackage import MyClass as theClass x4 = theClass() x4.f4() Copyright ©2000-14 CRS Enterprises Ltd 134 Packages Import loads all modules together executes __init__.py for each package import sys sys.path.append("lib") # load both packages together import mypackage.mysubpackage x = mypackage.mysubpackage.ModuleA.A() x.f(); loading mypackage x.g(); loading mysubpackage x.h() this is A.f() ... this is A.g() ... this is A.h() ... Copyright ©2000-14 CRS Enterprises Ltd mypackage/__init__.py mysubpackage/__init__.py ModuleA.py 135 Module Search Path When loading modules the interpreter searches the list of directories in sys.path first entry in sys.path can be an empty string refers to the current working directory other entries in sys.path may consist of directory names, .zip archive files, and .egg files order determines which modules are loaded import sys sys.path.append('mylib') Copyright ©2000-14 CRS Enterprises Ltd 136 Displaying Symbol Tables ... To display symbol table of main program use the global dictionary Iterate through the dictionary using iteritems() # use globals to get a list of symbols in main module # Jython returns a StringMap which needs to be # converted to a dictionary symbols = dict(globals()) #print all the symbols in module for key, value in symbols.iteritems(): print key, value Copyright ©2000-14 CRS Enterprises Ltd 137 ... Displaying Symbol Tables To display symbol table of a module use the module's dictionary Iterate through the dictionary using iteritems() #print all the symbols in myfunctions module for key, value in myfunctions.__dict__.iteritems(): print key, value Copyright ©2000-14 CRS Enterprises Ltd 138 Installing Third-Party Libraries Definitive resource for locating third-party libraries and extensions to Python is the Python Package Index (PyPI) http://pypi.python.org Installing third-party modules is usually straightforward use easy_install or pip use platform-native installer use a download a zip that comes with setup.py file to install type python setup.py install Copyright ©2000-14 CRS Enterprises Ltd 139 Chapter 11 11 Copyright ©2000-14 CRS Enterprises Ltd 141 Inheritance and Polymorphism Inheritance new style classes and object subtyping Abstract Classes interfaces OO contracts Polymorphism the good the bad (duck typing) Copyright ©2000-14 CRS Enterprises Ltd 142 Subclassing A class can inherit methods and state from another class the new class is called the subclass or derived class the original class is called the superclass or base class The subclass is a superset of the superclass inherits all the methods and state of the superclass can add extra methods and state of its own cannot remove and methods and state of the superclass methods in the superclass can be overridden by the subclass the subclass is defined in the terms of the differences from the superclass Copyright ©2000-14 CRS Enterprises Ltd 143 The Object Class object All classes have a single root object only for new style classes Person Object defines methods inherited by all Python classes Employee SalesPerson Copyright ©2000-14 CRS Enterprises Ltd 144 Constructors Subclass makes explicit call to CTORs in superclass class Person(object): def __init__(self, name): self.name = name class Employee(Person): def __init__(self, name, id): Person.__init__(self, name) self.id = id class SalesPerson(Employee): def __init__(self, name, id, region): Employee.__init__(self, name, id) self.region = region Employee IS A Person SalesPerson IS A Employee SalesPerson IS A Person p = Person("Anne") e = Employee("Beth", 7468) s = SalesPerson("Carol", 4712, "NE") Copyright ©2000-14 CRS Enterprises Ltd 145 The Substitution Rule Employee class extends the Person class Person SalesPerson class extends the Employee class Employee substitutes for Person object SalesPerson substitutes for Employee object Person object Copyright ©2000-14 CRS Enterprises Ltd Superclass extends Employee Subclass extends SalesPerson 146 Inheriting Methods class Person(object): def Print( ): ... class Employee(Person): def GetBonus( ): ... Person p Print( ) Employee e class Salesman(Employee): def GetBonus( ): ... Salesman s Print() Print( ) Employee.GetBonus( ) GetBonus( ) GetBonus( ) Copyright ©2000-14 CRS Enterprises Ltd 147 Overriding Superclass Methods Subclass can override any method of the superclass superclass method hidden from client code e = Employee("Beth", 7468) e.display() class Employee(Person): def display(self): Person.display(self) # alternatively search super classes for display method # super(Employee, self).display() # only for new style classes print "id=", self.id, Copyright ©2000-14 CRS Enterprises Ltd 148 Concrete and Abstract Classes Concrete class all methods are fully implemented may have instance variables objects can be instantiated Abstract class some methods are not implemented some methods are implemented may have instance variables objects cannot be instantiated Hoisting abstract classes used to hold "common" code from subclasses A concrete subclass must implement all abstract methods of its superclass Copyright ©2000-14 CRS Enterprises Ltd 149 Abstract Classes ... from abc import ABCMeta, abstractmethod, abstractproperty class Shape: __metaclass__ = ABCMeta @abstractmethod def display(self): pass @abstractproperty def name(self): pass Copyright ©2000-14 CRS Enterprises Ltd 150 ... Abstract Classes class Circle(Shape): def __init__(self, name): self.theName = name def display(self): print "Circle", self.name @property def name(self): return self.theName non abstract methods and instance variables automatically available must implement all abstract methods c = Circle("my-circle") print c.name c.display() Copyright ©2000-14 CRS Enterprises Ltd 151 Interfaces An interface similar to an abstract class, but ... all methods are abstract no instance variables allowed final class variables permitted (constants) Can't be instantiated A concrete class can implemented multiple interfaces multiple inheritance model extend only one class multiple inheritance model Copyright ©2000-14 CRS Enterprises Ltd 152 Polymorphic Methods An (optional) abstract method defined in interfaces and abstract classes not appropriate for the superclass to provide an implementation implemented by a subclasses Implementations each implementing subclass can provide its own implementation there can be 'many forms' of these implementations each implementation is called a Polymorphic method Copyright ©2000-14 CRS Enterprises Ltd 153 Polymorphism Polymorphic collections include objects of any subclass can call any of the methods of the superclass class Person(object): def Eat(self): pass def Drink(self): pass def Sleep(self): pass class Employee(Person): def Eat(self): pass def Drink(self): pass def Sleep(self): pass def NightOut(p): p.Drink() p.Drink() p.Eat() p.Drink() p.Sleep() class SalesPerson(Employee): def Eat(self): pass def Drink(self): pass def Sleep(self): pass Copyright ©2000-14 CRS Enterprises Ltd 154 Duck Typing Python allows polymorphic methods from classes not in the hierarchy not really sensible drawback of Python's weak (duck) typing class Person(object): def Eat(self): pass def Drink(self): pass def Sleep(self): pass def NightOut(p): p.Drink() p.Drink() p.Eat() p.Drink() p.Sleep() class Employee(Person): ... class SalesPerson(Employee): ... p = Person() e = Employee() s = SalesPerson() class Horse: def Eat(self): pass def Drink(self): pass def Sleep(self): pass NightOut(p) NightOut(e) NightOut(s) h = Horse() NightOut(h) Copyright ©2000-14 CRS Enterprises Ltd 155 Interfaces as Contracts Interfaces for the Class Implementor the interface defines all the methods and signatures for which the class designer must provide implementations Interfaces for the Class User the class user can write code assuming that implementations will be provided for all the methods in the interface The Contract each interface defines a contract between the class user and class implementor separates interface from implementation essential for good object oriented design Copyright ©2000-14 CRS Enterprises Ltd 156 Chapter 12 12 Copyright ©2000-14 CRS Enterprises Ltd 159 Further Topics Intrinsic Attributes for classes and objects Dynamic Statements exec and eval Operator Overloading numeric types list types Copyright ©2000-14 CRS Enterprises Ltd 160 The 5 Intrinsic Class Attributes __name__ __doc__ __module__ __dict__ __bases__ name of the class (read only) class documentation string module in which the class is defined map of all class attributes tuple of all base classes class Derived(Base): "This is the Derived class" def Display(self): pass print Derived.__name__ print Derived.__doc__ print Derived.__module__ print Derived.__dict__ print Derived.__bases__ Copyright ©2000-14 CRS Enterprises Ltd Derived This is the Derived class __main__ {'Display': <function Display at ... (<class __main__.Base at ... 161 The 2 Intrinsic Object Attributes __class__ the object's class __dict__ map of all the object's attributes class Derived(Base): "This is the Derived class" def Display(self): pass x = Derived() x.color = "red" x.width = 10 print x.__class__ print x.__dict__ __main__.Derived {'color': 'red', 'width': 10} Copyright ©2000-14 CRS Enterprises Ltd 162 exec and eval Statements exec x = 10 y = 20 codeFragment = raw_input("Please enter some code (e.g. 'print x + y'): ") exec codeFragment Please enter some code (e.g. 'print x + y'): print x * y + 1 201 eval x = 10 y = 20 codeFragment = str(input("Please enter an expression (e.g. 'x + y'): ")) result = eval(codeFragment) print "result is: ", result Please enter an expression (e.g. 'x + y'): x * y result is: 200 Copyright ©2000-14 CRS Enterprises Ltd 163 Operator Overloading Numeric Types class Time: def __init__(self, hrs, min): self.hrs = hrs self.min = min def __add__(self, other): hrs = self.hrs + other.hrs min = self.min + other.min if min >= 60: hrs = hrs + 1 min = min - 60 return Time(hrs, min) t3 = t1 + t2 def Display(self): print "Time is", self.hrs, self.min Copyright ©2000-14 CRS Enterprises Ltd 164 Operator Overloading Numeric Types class Time: def __init__(self, hrs, min): self.hrs = hrs self.min = min def __iadd__(self, other): self.hrs = self.hrs + other.hrs self.min = self.min + other.min if self.min >= 60: self.hrs = self.hrs + 1 self.min = self.min - 60 return self t1 += t3 def Display(self): print "Time is", self.hrs, self.min Copyright ©2000-14 CRS Enterprises Ltd 165 Operator Overloading Numeric Types class Time: def __init__(self, hrs, min): self.hrs = hrs self.min = min def __add__(self, other): hrs = self.hrs + other.hrs min = self.min + other.min if min >= 60: hrs = hrs + 1 min = min - 60 return Time(hrs, min) t1 = Time(5,30) t2 = Time(3,30) t3 = t1 + t2 t3.Display() def __iadd__(self, other): t1 += t3 self.hrs = self.hrs + other.hrs t1.Display() self.min = self.min + other.min if self.min >= 60: self.hrs = self.hrs + 1 self.min = self.min - 60 return self Time is 9 0 Time is 14 30 def Display(self): print "Time is", self.hrs, self.min Copyright ©2000-14 CRS Enterprises Ltd 166 Operator Overloading other Types Emulate other types Built-In Objects Sequences Slices Emulate Maps Special Methods to be Written e.g. for Maps __len__(self) __getitem__(self,key) __setitem__(self,key,value) __delitem__(self,key) Copyright ©2000-14 CRS Enterprises Ltd 167 Operator Overloading List Types class MyList: def __init__(self, p1, p2): self.theList = [ ] self.theList.append(p1) self.theList.append(p2) t1 = MyList(1,2) t2 = MyList(3,4) t3 = t1 + t2 def __add__(self, other): result = [ ] for item in self.theList: result.append(item) for item in other.theList: result.append(item) return result t1: [1,2] t2: [3,4] t3: [1,2,3,4] Copyright ©2000-14 CRS Enterprises Ltd 168 Overloading [ ] using __getitem__ class mydata: def __init__(self): self.data = "ABCDEFG" def __getitem__(self, i): return self.data[i] B ABCDEFG object = mydata() theChar = object[1] print theChar; for item in object: print item, Copyright ©2000-14 CRS Enterprises Ltd 169 Chapter 13 13 Copyright ©2000-14 CRS Enterprises Ltd 171 Pattern Matching Pattern Matching Splitting Substitution Comments Replacement Capture Patterns Greedy Matching Look Ahead Copyright ©2000-14 CRS Enterprises Ltd 172 Anchors and Selections selection indicates which characters to match [abc] any one character from list (a OR b OR c) [a-m] any one character from range (a OR b OR ... OR m) [^abc] any one character not in list (NOT a NOR b NOR c) . any one character \s any white space character \S any NON white space character \d any digit \D any NON digit \w any alphanumeric \W any NON alphanumeric anchors indicate context ^ start of string $ end of string \b on a word boundary \B NOT on a word boundary Copyright ©2000-14 CRS Enterprises Ltd 173 Repeat Counts repeat counts apply to the previous expression * 0 or more repeats + 1 or more repeats ? 0 or 1 repeats {n,m} n to m repeats {n,} at least n repeats {n} exactly n repeats Examples [aeiou]* [0-9]+ [0-9]{3,5} \.? 0 or more vowels 1 or more digits (\d+) 3 to 5 digits 0 or 1 periods \. matches a period the backslash negates the special meaning of the pattern that follows Copyright ©2000-14 CRS Enterprises Ltd 174 Pattern Matching Functions match match from the start of text search match anywhere in the text import re test = "-------ABC------------" pattern = r"\w+" pattern = re.compile(pattern) match = pattern.match(test) print match None match = pattern.search(test) print match.group() ABC Copyright ©2000-14 CRS Enterprises Ltd 175 Splitting Perhaps we want to split a string using a regular expression as a delimiter pattern.split(text) import re pattern = re.compile(r"\s*;\s*") text = "aaa ; bbb ;ccc ; ddd ; eee" list = pattern.split(text) print list ['aaa', 'bbb', 'ccc', 'ddd', 'eee'] Copyright ©2000-14 CRS Enterprises Ltd 176 Substitution Perhaps we want to substitute something for the matched pattern? Use pattern.sub(replacement, text) import re pattern = re.compile(r"\s*;\s*") text = "aaa ; bbb ;ccc ; ddd ; eee" newText = pattern.sub("---", text) print newText aaa---bbb---ccc---ddd---eee Copyright ©2000-14 CRS Enterprises Ltd 177 Using Comments Always a good idea to use comments regular expressions are difficult to read at the best of times import re string = "AAAA1111BBBB2222CCCC3333DDDD"; pattern = r""" ^ # start of line (.*?) # 0 or more characters # non greedy (\d+) # 1 or more digits (.*) # 0 or more characters $ # end of line """ compiledPattern = re.compile(pattern, re.VERBOSE) result = compiledPattern.search(string) Copyright ©2000-14 CRS Enterprises Ltd 178 More Advanced Searches Use ( ) in pattern to capture data import re text = "---111122223333333333334444555566667777---" pattern = "2+(3+)4+(5+)6+" # search for pattern pattern = re.compile(pattern) result = pattern.search(text) # print results print "full match: ", result.group(0) print "capture pattern 1: ", result.group(1) print "capture pattern 2: ", result.group(2) print "all captures: ", result.groups() Copyright ©2000-14 CRS Enterprises Ltd 179 Repeating Patterns Use findall() and finditer() to repeat searches import re text = "AB12CD34EF56GH" pattern = r"(\d+)" # find all occurrences of pattern matcher = re.findall(pattern, text) print matcher # iterate through finding the pattern for matcher in re.finditer(pattern, text): print matcher.groups(0) Copyright ©2000-14 CRS Enterprises Ltd ['12', '34', '56'] ('12',) ('34',) ('56',) 180 Greedy Patterns Greedy Patterns are the default Use ? to use non greedy matching text = "AAAA1111BBBB2222CCCC3333DDDD" greedyPattern = r"^(.+)(\d+)(.+)$" nonGreedyPattern = r"^(.+?)(\d+)(.+)$" ^(.+)(\d+)(.+)$ Greedy: <AAAA1111BBBB2222CCCC333><3><DDDD> ^(.+?)(\d+)(.+)$ Non-Greedy: <AAAA><1111><BBBB2222CCCC3333DDDD> Copyright ©2000-14 CRS Enterprises Ltd 181 Look Ahead and Look Behind (?= ) (?! ) (?<= ) (?<! ) peek ahead matching RE peek ahead not matching RE peek behind matching RE peek behind not matching RE \w+[.](?!bat)\w+$ ?!bat not "bat" filename.ext Copyright ©2000-14 CRS Enterprises Ltd 182 Building Patterns Translation patterns can be built from hashes e.g. translate all occurrences of mon to Monday, tue to Tuesday etc import re def replaceGroup(matcher): key = matcher.group(1) return days[key] days = { 'mon' : 'Monday', 'tue' : 'Tuesday', 'wed' : 'Wednesday', 'thu' : 'Thursday', 'fri' : 'Friday' } pattern = "(" + "|".join(days.keys()) + ")" compiledPattern = re.compile(pattern) print "pattern: ", pattern text = '''The course starts on mon, continues on tue, but wed is the last day''' for matcher in re.finditer(compiledPattern, text): text = compiledPattern.sub(replaceGroup, text, 1) print text Copyright ©2000-14 CRS Enterprises Ltd 183 Copyright ©2000-14 CRS Enterprises Ltd 184 Chapter 14 14 Copyright ©2000-14 CRS Enterprises Ltd 185 Unit Test Unittest framework DocTest PyTest Copyright ©2000-14 CRS Enterprises Ltd 186 Components of Unittest test fixture code run to prepare for one or more tests e.g. start a server any associate cleanup actions test case unit of testing implemented as a method of test class test suite a collection of test cases used to aggregate tests that should be executed together. test runner component which orchestrates the execution of tests provides output relating to the success or failure of the tests Copyright ©2000-14 CRS Enterprises Ltd 187 Structure of Test Class derive from unittest.TestCase setUp call before each test tearDown called after each test import unittest execute tests by calling unittest.main() test names must begin with test... class testPoint(unittest.TestCase): def setUp(self): # called before each test executes def testA(self): ... def testB(self): ... def testC(self): ... def testD(self): ... if __name__ == '__main__': unittest.main() Copyright ©2000-14 CRS Enterprises Ltd 188 Structure of a Test Case Use assertEqual() to check the output of a test is correct other functions available def testMoveBy2(self): """moveBy test(2)""" self.point.moveBy(5, 2) self.assertEqual(self.point.display(), "8,7") FAIL: moveBy test(2) ---------------------------------------------------------------------Traceback (most recent call last): File "C:\_Eclipse\Python\Unit Test\unit-testing-1.py", line 29, in testMoveBy2 self.assertEqual(self.point.display(), "8,7") AssertionError: '8,6' != '8,7' Copyright ©2000-14 CRS Enterprises Ltd 189 Test Functions assertEqual() check for an expected result assert_() verify a condition assertRaises() verify that an expected exception gets raised Copyright ©2000-14 CRS Enterprises Ltd 190 Test Suites Tests can be grouped into suites def suite(): suite = unittest.TestSuite() suite.addTest(testPoint('testConstructor')) suite.addTest(testPoint('testMoveBy1')) suite.addTest(testPoint('testDistance1')) return suite if __name__ == '__main__': mySuite = suite() unittest.TextTestRunner(verbosity=0).run(mySuite) Copyright ©2000-14 CRS Enterprises Ltd 191 DocTest DocTest module searches for text that look like interactive Python sessions executes those sessions to verify that they work exactly as shown Tests are embedded in code easy to define tests can cause clutter Copyright ©2000-14 CRS Enterprises Ltd 192 01 simple example Use doctest.testmod(...) many parameters, but usually just use verbose=True def cube(x): """ The cube function returns x * x * x >>> cube(3) 27 >>> cube(-1) -1 """ return x*x*x if __name__ == '__main__': import doctest doctest.testmod(verbose = True) Copyright ©2000-14 CRS Enterprises Ltd 193 02 formatting Tests can be fuzzy ... used to omit some results whitespace not relevant if ELLIPIS and NORMALIZE_WHITESPACE specified def squares(a, b): """ returns all the squares in range a..b >>> squares(1,10) # doctest:+ELLIPSIS +NORMALIZE_WHITESPACE [1, 4, ..., 100] """ answer=[] for i in range(a,b+1): answer.append(i*i) return answer Copyright ©2000-14 CRS Enterprises Ltd 194 03 failures Failures reported with line numbers and erroneous result def sumsquares(n): """ Trying: 1+4+9+16 = 30 (not 30457) sumsquares( 4 ) >>> sumsquares( 4 ) Expecting: 30457 30457 """ ********************************************************************** sum = 0 File "C:\_Eclipse\Advanced Python\src\Unit Framework forTest i in range(n+1): Failed example: sum += square(i) sumsquares( 4 ) return sum Expected: 30457 Got: 30 Copyright ©2000-14 CRS Enterprises Ltd 195 04 exceptions Exceptions can be catered for in the tests use ... to suppress unnecessary information def square(x): """ This function squares a number >>> square(-3) 9 >>> square(16) Traceback (most recent call last): ... ValueError: input too large """ if x > 10: raise ValueError('input too large') else: return x*x Copyright ©2000-14 CRS Enterprises Ltd 196 PyTest PyTest runs as a separate program inspects code for methods beginning with test_ and runs them If you need to install PyTest, use: easy_install -U py To run tests, go to a command prompt and type: py.test myExample.py Copyright ©2000-14 CRS Enterprises Ltd 197 01 simple example Add tests as methods in your modules use assert statements def square(x): return x * x def test_squares(): assert square(6) == 36 # succeeds assert square(10) == 99 # fails Copyright ©2000-14 CRS Enterprises Ltd 198 02 multiple tests Use iterators to create multiple tests Use setup_class() class TestSquare: for initial test conditions def setup_class(self): self.m = maths.Maths() def is_square(self, n, expected): self.m.setX(n) assert self.m.square() == expected def test_squares(self): # set up 5 tests (the last one fails!) inputs = ( 4, 7, 10, 20, 25) outputs = (16, 49, 100, 400, -1) for i, o in zip(inputs, outputs): yield self.is_square, i, o Copyright ©2000-14 CRS Enterprises Ltd 199