View
222
Download
0
Category
Tags:
Preview:
Citation preview
Copyright ©2000-14 CRS Enterprises Ltd 1
Python Fundamentals
by
Chris Seddon
Copyright ©2000-14 CRS Enterprises Ltd 3
Python Fundamentals1. 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 5
Chapter 1
1
Copyright ©2000-14 CRS Enterprises Ltd 6
Introduction to Python
IronPython
Copyright ©2000-14 CRS Enterprises Ltd 7
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 programmingoften 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 8
Advantages of PythonPython is best used
to develop small programs and scripts
simple programs can be created very quickly
Python can be used for large-scale programming projectssophisticated 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 startmore simplified and natural coding style than Perl, Rexx and VBScript
highly portable
Copyright ©2000-14 CRS Enterprises Ltd 9
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 Librariesuses Java libraries because of the JVM
NOT standard Python libraries
can be a problem sometimes
Copyright ©2000-14 CRS Enterprises Ltd 10
Everything is InterpretedPython 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
JVMJVM
myJava.javamyJava.java
myJava.classmyJava.class
myPython.pymyPython.py
Target Hardware
Target Hardware
Copyright ©2000-14 CRS Enterprises Ltd 11
PerformancePython 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 performanceprofile, cProfile
Copyright ©2000-14 CRS Enterprises Ltd 12
Invoking PythonUse 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 choicePyDev is very mature
Copyright ©2000-14 CRS Enterprises Ltd 13
A "Hello World" ExampleThe Hello World example is a trivial one liner in Python;
you don’t even require a semi-colon!
print "Hello World!"print "Hello World!"
Copyright ©2000-14 CRS Enterprises Ltd 14
Further ExampleThe Hello World example is a trivial one liner in Python;
you don’t even require a semi-colon!
# this is a commentx = 100y = 200if x + y < 500: print "sum is less than 500"
# this is a commentx = 100y = 200if x + y < 500: print "sum is less than 500"
indent
colon
Copyright ©2000-14 CRS Enterprises Ltd 17
Chapter 2
2
Copyright ©2000-14 CRS Enterprises Ltd 18
Control StructuresStatements
if
for
while
Copyright ©2000-14 CRS Enterprises Ltd 19
if Statements
x = int(raw_input("Please enter an integer: "))
if x < 0: print 'Negative'
x = int(raw_input("Please enter an integer: "))
if x < 0: print 'Negative'
Please enter an integer: -5Negative
Please enter an integer: -5Negative
Copyright ©2000-14 CRS Enterprises Ltd 20
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'
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: 66x is positivethe square of x is 4356the cube of x is 287496End of if-statement
Please enter a positive integer: 66x is positivethe square of x is 4356the cube of x is 287496End of if-statement
Copyright ©2000-14 CRS Enterprises Ltd 21
if-else Statements
x = int(raw_input("Please enter an integer: "))
if x < 0: print 'Negative'else: print 'Not negative'
x = int(raw_input("Please enter an integer: "))
if x < 0: print 'Negative'else: print 'Not negative'
Please enter an integer: 5Not negative
Please enter an integer: -5Negative
Please enter an integer: 5Not negative
Please enter an integer: -5Negative
Copyright ©2000-14 CRS Enterprises Ltd 22
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'
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'
Please enter an integer: -3NegativePlease enter an integer: 0ZeroPlease enter an integer: 1OnePlease enter an integer: 7Greater than one
Please enter an integer: -3NegativePlease enter an integer: 0ZeroPlease enter an integer: 1OnePlease enter an integer: 7Greater than one
Copyright ©2000-14 CRS Enterprises Ltd 23
Conditional if Statements
x = 100result = (-1 if x < 0 else 1)print result
x = -200result = (-1 if x < 0 else 1)print result
x = 100result = (-1 if x < 0 else 1)print result
x = -200result = (-1 if x < 0 else 1)print result
1-1
1-1
Copyright ©2000-14 CRS Enterprises Ltd 24
for Statements
for x in (10,17,24,31,38,45,52,59,66,73,80,87,94): print x,
for x in range(10,100,7): print x,
for x in (10,17,24,31,38,45,52,59,66,73,80,87,94): print x,
for x in range(10,100,7): print x,
10 17 24 31 38 45 52 59 66 73 80 87 9410 17 24 31 38 45 52 59 66 73 80 87 94
10 17 24 31 38 45 52 59 66 73 80 87 9410 17 24 31 38 45 52 59 66 73 80 87 94
Copyright ©2000-14 CRS Enterprises Ltd 25
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: breakelse: print "only get here if all iterations succeed ..."
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: breakelse: print "only get here if all iterations succeed ..."
1 2 3 4 5 6 only get here if all iterations succeed ...1 2 3 4
1 2 3 4 5 6 only get here if all iterations succeed ...1 2 3 4
Copyright ©2000-14 CRS Enterprises Ltd 26
Using rangeuse range to iterate a fixed number of times
for x in range(1,10): print x,
for x in range(1,10): print x,
1 2 3 4 5 6 7 8 91 2 3 4 5 6 7 8 9
Copyright ©2000-14 CRS Enterprises Ltd 27
while Statements
formula = 0x = 0
while formula < 1000: x = x + 1 formula = 2*x*(x + 1) print x, formula
formula = 0x = 0
while formula < 1000: x = x + 1 formula = 2*x*(x + 1) print x, formula
1 42 123 244 405 606 847 1128 1449 18010 22011 26412 31213 36414 42015 48016 54417 61218 68419 76020 84021 92422 1012
1 42 123 244 405 606 847 1128 1449 18010 22011 26412 31213 36414 42015 48016 54417 61218 68419 76020 84021 92422 1012
Copyright ©2000-14 CRS Enterprises Ltd 29
Chapter 3
3
Copyright ©2000-14 CRS Enterprises Ltd 30
Basic Data TypesBasic Types
int
long
boolean
float
complex
string
Copyright ©2000-14 CRS Enterprises Ltd 31
Data TypesEverything is an object
including all types discussed in this chapter
full documentation for the Java types is online
Several types are immutablestrings, tuples
Sometimes objects behave as though immutableif 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 32
Built in Typesint
C long
includes Booleans
hex and octal numbers available
booleanTrue, False, and, or
floatC double type (13 sig. fig.)
longunlimited precision
e.g. 10000000000000000000000000
complexreal and imaginary parts are each implemented using Java double
e.g. (5.0+3.1j)
Copyright ©2000-14 CRS Enterprises Ltd 33
IntegersLimited precision
decimals, octal and hexadecimal
# integersx = 100x += 1print type(x)print x
x = 053print x
x = 0xFFprint x
# integersx = 100x += 1print type(x)print x
x = 053print x
x = 0xFFprint x
<type 'int'>10143255
<type 'int'>10143255
Copyright ©2000-14 CRS Enterprises Ltd 34
BooleansValues
True, False
Operatorsand, or
x = Truey = False
z = x or yprint z
z = x and yprint zprint type(z)
x = Truey = False
z = x or yprint z
z = x and yprint zprint type(z)
True
False<type 'bool'>
True
False<type 'bool'>
Copyright ©2000-14 CRS Enterprises Ltd 35
Floating Point13 significant figures on 64 bit implementation
no exact representation
# floating pointx = 1e4 + 0.1e-4format = "%32.20g"print type(x)print (format % x)
# floating pointx = 1e4 + 0.1e-4format = "%32.20g"print type(x)print (format % x)
<type 'float'> 10000.000009999999747
<type 'float'> 10000.000009999999747
Copyright ©2000-14 CRS Enterprises Ltd 36
Complex Numbersfloating types
real and imaginary partscan be extracted separately
x = (+2.5-3.4j) - (-1.4+1.0j)print type(x)print x
print x.realprint x.imag
x = (+2.5-3.4j) - (-1.4+1.0j)print type(x)print x
print x.realprint x.imag
<type 'complex'>(3.9-4.4j)3.9-4.4
<type 'complex'>(3.9-4.4j)3.9-4.4
Copyright ©2000-14 CRS Enterprises Ltd 37
Integers are Immutablex 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 immutablex just points to a different object
the original object gets garbage collected
x = 100print id(x)
x = x + 1print id(x)
x = 100print id(x)
x = x + 1print id(x)
10053412
10053400
10053412
10053400
Copyright ©2000-14 CRS Enterprises Ltd 38
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
phrase = x + " " + y + " " + zprint phrase.upper()
x = 'hello'y = "from"z = """the planet earth""" print type(x)print x, y, z
phrase = x + " " + y + " " + zprint phrase.upper()
<type 'str'>hello from the planet earthHELLO FROM THE PLANET EARTH
<type 'str'>hello from the planet earthHELLO FROM THE PLANET EARTH
Copyright ©2000-14 CRS Enterprises Ltd 39
... StringsMany 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()
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()
---abc:xyz:123---abc:XYZ:123---
---abc@XYZ@123------abc:XYZ:123
['---abc', 'XYZ', '123---']abc:XYZ:123
---ABC:xyz:123------ABC:XYZ:123---
---abc:xyz:123---abc:XYZ:123---
---abc@XYZ@123------abc:XYZ:123
['---abc', 'XYZ', '123---']abc:XYZ:123
---ABC:xyz:123------ABC:XYZ:123---
Copyright ©2000-14 CRS Enterprises Ltd 40
... StringsMore string methods ...
count(sub) number of occurrences of substring find(sub) index in the string where substring is found
isalnum() true if string is alphanumericisalpha() true if string is alphabetic
isdigit() true if string is all digits
join(seq) concatenate all the strings in the sequencepartition(sep) split the string at the first occurrence of sep and return a 3-
tuple
split(sep) return a list of the words in the string using sep as the delimiter
count(sub) number of occurrences of substring find(sub) index in the string where substring is found
isalnum() true if string is alphanumericisalpha() true if string is alphabetic
isdigit() true if string is all digits
join(seq) concatenate all the strings in the sequencepartition(sep) split the string at the first occurrence of sep and return a 3-
tuple
split(sep) return a list of the words in the string using sep as the delimiter
Copyright ©2000-14 CRS Enterprises Ltd 43
Chapter 4
4
Copyright ©2000-14 CRS Enterprises Ltd 44
Advanced Data TypesSequence Types
list (mutable) use [ ]
tuple (immutable) use ( )
set no duplicates
Dictionary Typesdict (mutable) use { }
Copyright ©2000-14 CRS Enterprises Ltd 45
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)
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)
<type 'list'>[ ] ----- 0[1] ----- 1[1, 2, 3] ----- 3[1, 'mixed', 2, 'list'] ----- 4[[1, 2], [3, 4]] ----- 2
<type 'list'>[ ] ----- 0[1] ----- 1[1, 2, 3] ----- 3[1, 'mixed', 2, 'list'] ----- 4[[1, 2], [3, 4]] ----- 2
Copyright ©2000-14 CRS Enterprises Ltd 46
... ListLists can be extended with
extend or append
Elements can be modifiedobject reference gets changed
Can contain immutable itemssuch as tuples
list1 = [[1,2],[3,4]]
# notation for accessing listsprint list1print list1[1]print list1[1][0]
# modifying listslist1[1][0] = 99print list1[1][0]
list1 = [[1,2],[3,4]]
# notation for accessing listsprint list1print list1[1]print list1[1][0]
# modifying listslist1[1][0] = 99print list1[1][0]
# append and extend are equivalentlist2 = [10, 20, 30]list = [ ]list.extend(list1)list.append(list2)print list
# lists can contain tupleslist3 = [(1,2), (3,4), (5,6)]print list3
# append and extend are equivalentlist2 = [10, 20, 30]list = [ ]list.extend(list1)list.append(list2)print list
# lists can contain tupleslist3 = [(1,2), (3,4), (5,6)]print list3
Copyright ©2000-14 CRS Enterprises Ltd 47
Tupleimmutable
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)
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)
<type 'tuple'>( ) ----- 0(1,) ----- 1(1, 2, 3) ----- 3(1, 'mixed', 2, 'tuple') ----- 4((1, 2), (3, 4)) ----- 2
<type 'tuple'>( ) ----- 0(1,) ----- 1(1, 2, 3) ----- 3(1, 'mixed', 2, 'tuple') ----- 4((1, 2), (3, 4)) ----- 2
Copyright ©2000-14 CRS Enterprises Ltd 48
Accessing Lists and Tuplesonly 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] = 99mylist.append(40)print mylist
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] = 99mylist.append(40)print mylist
[10, 99, 30, 40][10, 99, 30, 40]
Copyright ©2000-14 CRS Enterprises Ltd 49
Casting between Lists and Tuplesuse a cast to convert
tuple( ... )
list( ...)
theList = [2, 3, 5, 7, 11, 13, 17]myTuple = tuple(theList)myList = list(myTuple)
print myTupleprint myList
theList = [2, 3, 5, 7, 11, 13, 17]myTuple = tuple(theList)myList = list(myTuple)
print myTupleprint myList
(2, 3, 5, 7, 11, 13, 17)[2, 3, 5, 7, 11, 13, 17]
(2, 3, 5, 7, 11, 13, 17)[2, 3, 5, 7, 11, 13, 17]
Copyright ©2000-14 CRS Enterprises Ltd 50
SlicesSequences 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 slicingreplaces 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:];
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:];
blue['blue', 'green']['blue', 'green', 'white', 'black']['green', 'white']['black', 'white', 'green']
['red', 'blue', 'purple', 'cyan', 'black']
blue['blue', 'green']['blue', 'green', 'white', 'black']['green', 'white']['black', 'white', 'green']
['red', 'blue', 'purple', 'cyan', 'black']
Copyright ©2000-14 CRS Enterprises Ltd 51
Set and FrozenSetunordered 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"
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"
set(['Friday', 'Tuesday', 'Thursday', 'Wednesday', 'Monday'])
member
not a member
set(['Friday', 'Tuesday', 'Thursday', 'Wednesday', 'Monday'])
member
not a member
Copyright ©2000-14 CRS Enterprises Ltd 52
Set and FrozenSetSet supports mathematical operations
union, intersection and symmetric difference
sequence1 = 1, 3, 5, 7, 5, 4, 3, 2, 1sequence2 = 2, 4, 6, 8, 6, 4, 3, 2, 1set1 = set(sequence1)set2 = set(sequence2)print(set1)print(set2)
unionSet = set1.union(set2)intersectionSet = set1.intersection(set2)differenceSet = set1.symmetric_difference(set2)print(unionSet)print(intersectionSet)print(differenceSet)
sequence1 = 1, 3, 5, 7, 5, 4, 3, 2, 1sequence2 = 2, 4, 6, 8, 6, 4, 3, 2, 1set1 = set(sequence1)set2 = set(sequence2)print(set1)print(set2)
unionSet = set1.union(set2)intersectionSet = set1.intersection(set2)differenceSet = set1.symmetric_difference(set2)print(unionSet)print(intersectionSet)print(differenceSet)
set([1, 2, 3, 4, 5, 7])set([1, 2, 3, 4, 6, 8])
set([1, 2, 3, 4, 5, 7])set([1, 2, 3, 4, 6, 8])
set([1, 2, 3, 4, 5, 6, 7, 8])set([1, 2, 3, 4])set([5, 6, 7, 8])
set([1, 2, 3, 4, 5, 6, 7, 8])set([1, 2, 3, 4])set([5, 6, 7, 8])
Copyright ©2000-14 CRS Enterprises Ltd 53
Not Definedspecial type
NoneType
x = 120print type(x)print x
x = None # not definedprint type(x)print x
if (x == None): x = 240
print x
x = 120print type(x)print x
x = None # not definedprint type(x)print x
if (x == None): x = 240
print x
<type 'int'>120<type 'NoneType'>None240
<type 'int'>120<type 'NoneType'>None240
Copyright ©2000-14 CRS Enterprises Ltd 55
Chapter 5
5
Copyright ©2000-14 CRS Enterprises Ltd 56
Dictionarieskeys and values
inserting, updating and deleting
common methods
Copyright ©2000-14 CRS Enterprises Ltd 57
Dictionarylike a database table
also called hash, associative array
key:value pairskeys 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"]
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"]
<type 'dict'>12('Jun', 'Jul', 'Aug')
<type 'dict'>12('Jun', 'Jul', 'Aug')
Copyright ©2000-14 CRS Enterprises Ltd 58
Working with DictionariesDictionaries are mutable
modify existing entries
add new entries
Key Order is indeterminatebecause of hashing algorithm
salary = {"zak": 34000, "sara": 27000,"pedro": 52000,"jo": 12500,"zoe": 66000
}print salary["pedro"]salary["jo"] = 15000; # modify existingsalary["peter"] = 35000 # add new entry
salary = {"zak": 34000, "sara": 27000,"pedro": 52000,"jo": 12500,"zoe": 66000
}print salary["pedro"]salary["jo"] = 15000; # modify existingsalary["peter"] = 35000 # add new entry
Copyright ©2000-14 CRS Enterprises Ltd 59
InitializationUse { } or constructor
salary1 = {"zak": 34000, "sara": 27000,"pedro": 52000,"kilas": 12500,"zoe": 66000
}
salary1 = {"zak": 34000, "sara": 27000,"pedro": 52000,"kilas": 12500,"zoe": 66000
}
salary2 = dict( 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 60
Inserting or UpdatingNew elements ...
are added
Existing elements ...are updated
salary["sara"] = 28000salary["sara"] = 28000
salary["sara"] = 29000salary["sara"] = 29000
Copyright ©2000-14 CRS Enterprises Ltd 61
Removing KeysUse del statement
or
Use pop
del salary["zak"]del salary["zak"]
salary.pop("zak")salary.pop("zak")
Copyright ©2000-14 CRS Enterprises Ltd 62
Removing ValuesAssign key to None
previous value gets garbage collected
salary["sara"] = Nonesalary["sara"] = None
Copyright ©2000-14 CRS Enterprises Ltd 63
Common Functions ...Extract all the keys, and all the values
# create list of keystheKeys = salary.keys()
# create list of valuestheValues = salary.values()
# create list of keystheKeys = salary.keys()
# create list of valuestheValues = salary.values()
Copyright ©2000-14 CRS Enterprises Ltd 64
... Common FunctionsWork with keys, values or both
# print all the keysfor key in salary.iterkeys(): print key,print
# print all the valuesfor value in salary.itervalues(): print value,print
# print all <key,value> pairsfor key, value in salary.iteritems(): print key, value
# print all the keysfor key in salary.iterkeys(): print key,print
# print all the valuesfor value in salary.itervalues(): print value,print
# print all <key,value> pairsfor key, value in salary.iteritems(): print key, value
Copyright ©2000-14 CRS Enterprises Ltd 67
Chapter 6
6
Copyright ©2000-14 CRS Enterprises Ltd 68
FunctionsSimple functions
Passing parameters
Returning multiple results
Pass by value
Working with lists
Pass by object reference
Object identity
Copyright ©2000-14 CRS Enterprises Ltd 69
Simple Functions
def square(n): print n * n
square(5)square(6)square(7)
def square(n): print n * n
square(5)square(6)square(7)
253649
253649
Copyright ©2000-14 CRS Enterprises Ltd 70
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)
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.56.611.5
6.56.611.5
Copyright ©2000-14 CRS Enterprises Ltd 71
A swap Function
def swap(a,b): return b,a
x = 100y = 200
[x,y] = swap(x,y)print x, y
def swap(a,b): return b,a
x = 100y = 200
[x,y] = swap(x,y)print x, y
200 100200 100
Copyright ©2000-14 CRS Enterprises Ltd 72
How not to Swap
def no_swap(a,b): temp = a a = b b = temp
x = 100y = 200
no_swap(x,y)print x, y
def no_swap(a,b): temp = a a = b b = temp
x = 100y = 200
no_swap(x,y)print x, y
100 200100 200
Copyright ©2000-14 CRS Enterprises Ltd 73
Object Identity
def readIt(a): print a,"id3 =",id(a)
def modifyIt(a): a = a + 1 print a,"id4 =",id(a)
x = 100print x,"id1 =",id(x)
x = x + 1print x,"id2 =",id(x)
readIt(x)modifyIt(x)
def readIt(a): print a,"id3 =",id(a)
def modifyIt(a): a = a + 1 print a,"id4 =",id(a)
x = 100print x,"id1 =",id(x)
x = x + 1print x,"id2 =",id(x)
readIt(x)modifyIt(x)
100 id1 = 12160993101 id2 = 9774375101 id3 = 9774375102 id4 = 28991818
100 id1 = 12160993101 id2 = 9774375101 id3 = 9774375102 id4 = 28991818
Copyright ©2000-14 CRS Enterprises Ltd 74
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 = [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 = 9774375list2 id = 28991818list3 id = 21579068list1 id = 9774375
list1 id = 9774375list2 id = 28991818list3 id = 21579068list1 id = 9774375
Copyright ©2000-14 CRS Enterprises Ltd 75
Pass by Object Reference
def modifyList(mylist): del mylist[0] print id(mylist),mylist
theList = [2, 3, 5, 7, 11]print id(theList), theListmodifyList(theList)print id(theList), theList
def modifyList(mylist): del mylist[0] print id(mylist),mylist
theList = [2, 3, 5, 7, 11]print id(theList), theListmodifyList(theList)print id(theList), theList
12160993 [2, 3, 5, 7, 11]12160993 [3, 5, 7, 11]12160993 [3, 5, 7, 11]
12160993 [2, 3, 5, 7, 11]12160993 [3, 5, 7, 11]12160993 [3, 5, 7, 11]
Copyright ©2000-14 CRS Enterprises Ltd 76
Swapping Lists
def swap(list): list[0],list[1] = list[1],list[0]
mylist = [100,200]
swap(mylist)print mylist
def swap(list): list[0],list[1] = list[1],list[0]
mylist = [100,200]
swap(mylist)print mylist
[200, 100][200, 100]
Copyright ©2000-14 CRS Enterprises Ltd 77
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 list1print list2
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 list1print list2
[10, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 99][10, 18, 19, 20, 99]
[10, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 99][10, 18, 19, 20, 99]
Copyright ©2000-14 CRS Enterprises Ltd 78
Function Aliases
def fib(n): a, b = 0, 1 while b < n: print b, a, b = b, a+b print
fib(15000)
f = fibf(100)
def fib(n): a, b = 0, 1 while b < n: print b, a, b = b, a+b print
fib(15000)
f = fibf(100)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 109461 1 2 3 5 8 13 21 34 55 89
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 109461 1 2 3 5 8 13 21 34 55 89
Copyright ©2000-14 CRS Enterprises Ltd 79
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)
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= 19.0 b= 6.2 c= 4.8a= 17.0 b= 10.0 c= 100.0a= 17.0 b= 21.0 c= 100.0a= 17.0 b= 10.0 c= 0.0
a= 19.0 b= 6.2 c= 4.8a= 17.0 b= 10.0 c= 100.0a= 17.0 b= 21.0 c= 100.0a= 17.0 b= 10.0 c= 0.0
Copyright ©2000-14 CRS Enterprises Ltd 80
Lambda Functions
sum = lambda x, y: x + y
print sum(1,2)print sum(5,9)print sum(10,20)
sum = lambda x, y: x + y
print sum(1,2)print sum(5,9)print sum(10,20)
31430
31430
Copyright ©2000-14 CRS Enterprises Ltd 81
Passing Tuples and Lists
def f(*args): print 'args:', args a = (3,4,7,8)b = [3,4,7,8]
f(1,3,4,7,8,9) # pass multiple argsf(1,a,9) # pass int, tuple, intf(1,b,9) # pass int, list, intf(1,*a) # treat tuple as multiple argsf(1,*b) # treat list as multiple args
def f(*args): print 'args:', args a = (3,4,7,8)b = [3,4,7,8]
f(1,3,4,7,8,9) # pass multiple argsf(1,a,9) # pass int, tuple, intf(1,b,9) # pass int, list, intf(1,*a) # treat tuple as multiple argsf(1,*b) # treat list as multiple args
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)
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)
Copyright ©2000-14 CRS Enterprises Ltd 82
Passing Named Parameters
def f(x,y,**params):print 'x,y:', x, yprint 'params:', params
f(13,7, Jan=1, Feb=2, May=5, Dec=12)
def f(x,y,**params):print 'x,y:', x, yprint 'params:', params
f(13,7, Jan=1, Feb=2, May=5, Dec=12)
x,y: 13 7params: {'Dec': 12, 'May': 5, 'Jan': 1, 'Feb': 2}
x,y: 13 7params: {'Dec': 12, 'May': 5, 'Jan': 1, 'Feb': 2}
Copyright ©2000-14 CRS Enterprises Ltd 83
Stub Functions
def myStub(x, y): pass
myStub(5,6)myStub(1,10)myStub(0,7)
def myStub(x, y): pass
myStub(5,6)myStub(1,10)myStub(0,7)
Copyright ©2000-14 CRS Enterprises Ltd 85
Chapter 7
7
Copyright ©2000-14 CRS Enterprises Ltd 86
Exception HandlingKeywords
try
except
finally
raise
assert
Copyright ©2000-14 CRS Enterprises Ltd 87
try-except Statements
array = [1,2,3,4,5,6]
try: for x in array: print x, array[x] print "Exiting try block"
except IndexError,target: print "... entering except block" print target
array = [1,2,3,4,5,6]
try: for x in array: print x, array[x] print "Exiting try block"
except IndexError,target: print "... entering except block" print target
2 33 44 55 66 ... entering except blocklist index out of range
2 33 44 55 66 ... entering except blocklist index out of range
this is never executed
exception thrown here
exception type
object reference
Copyright ©2000-14 CRS Enterprises Ltd 88
try-except-else Statements
from math import sqrtx = int(raw_input("Enter positive integer: "))
try: root = sqrt(x)except: print "... entering except block"else: print "... entering else block" print root
from math import sqrtx = int(raw_input("Enter positive integer: "))
try: root = sqrt(x)except: print "... entering except block"else: print "... entering else block" print root
Enter positive integer: 25... entering else block5.0
Enter positive integer: -25... entering except block
Enter positive integer: 25... entering else block5.0
Enter positive integer: -25... entering except block
no exception
exception occurs
Copyright ©2000-14 CRS Enterprises Ltd 89
try-finally Statements
array = [1,2,3,4,5,6]
try: for x in array: print array[x - 1],finally: print "... entering finally block"
try: for x in array: print array[x * 2],finally: print "... entering finally block"
array = [1,2,3,4,5,6]
try: for x in array: print array[x - 1],finally: print "... entering finally block"
try: for x in array: print array[x * 2],finally: print "... entering finally block"
1 2 3 4 5 6 ... entering finally block3 5 ... entering finally blockIndexError: list index out of range
1 2 3 4 5 6 ... entering finally block3 5 ... entering finally blockIndexError: list index out of range
guaranteed to be calledeven if exception occurs
Copyright ©2000-14 CRS Enterprises Ltd 90
raise Statements
array = [1,2,3,-4,5,6]
try: for x in array: if x < 0: raise ValueError, "array index is negative!" print x,except ValueError, value: print print "... entering except block: " + str(value)
array = [1,2,3,-4,5,6]
try: for x in array: if x < 0: raise ValueError, "array index is negative!" print x,except ValueError, value: print print "... entering except block: " + str(value)
1 2 3... entering except block: array index is negative!
1 2 3... entering except block: array index is negative!
exception type
object reference
Copyright ©2000-14 CRS Enterprises Ltd 91
Unified try except finallyIn 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-blockfinally: final-block
try: block-1 ...except Exception1: handler-1 ...except Exception2: handler-2 ...else: else-blockfinally: final-block
Copyright ©2000-14 CRS Enterprises Ltd 92
Nested Exceptions
def f1(): print "Entering f1" f2() print "Leaving f1"
def f2(): print "Entering f2" f3() print "Leaving f2" def f3(): print "Entering f3" raise Exception("Some exception") print "Leaving f3" try: f1()except Exception, reason: print reason
def f1(): print "Entering f1" f2() print "Leaving f1"
def f2(): print "Entering f2" f3() print "Leaving f2" def f3(): print "Entering f3" raise Exception("Some exception") print "Leaving f3" try: f1()except Exception, reason: print reason
Entering f1Entering f2Entering f3Some exception
Entering f1Entering f2Entering f3Some exception
regarded as partof the try block
never executed
Copyright ©2000-14 CRS Enterprises Ltd 93
Standard ExceptionsException
StopIteration
StandardError
BufferError
ArithmeticError
FloatingPointErro
OverflowError
ZeroDivisionError
AssertionError
AttributeError
EnvironmentError
IOError
OSError
EOFError
ImportError
LookupError
IndexError
KeyError
ExceptionStopIteration
StandardError
BufferError
ArithmeticError
FloatingPointErro
OverflowError
ZeroDivisionError
AssertionError
AttributeError
EnvironmentError
IOError
OSError
EOFError
ImportError
LookupError
IndexError
KeyError
MemoryError
NameError
UnboundLocalError
ReferenceError
RuntimeError
NotImplementedError
SyntaxError
IndentationError
TabError
SystemError
TypeError
ValueError
UnicodeError
UnicodeDecodeError
UnicodeEncodeError
UnicodeTranslateError
MemoryError
NameError
UnboundLocalError
ReferenceError
RuntimeError
NotImplementedError
SyntaxError
IndentationError
TabError
SystemError
TypeError
ValueError
UnicodeError
UnicodeDecodeError
UnicodeEncodeError
UnicodeTranslateError
Copyright ©2000-14 CRS Enterprises Ltd 94
User Defined ExceptionsAlways subclass Exception
class MyError(Exception): def __init__(self, value): self.value = value
class MyError(Exception): def __init__(self, value): self.value = value
try: raise MyError(2*2)except MyError as e: print 'My exception occurred, value:', e.value
try: raise MyError(2*2)except MyError as e: print 'My exception occurred, value:', e.value
My exception occurred, value: 4My exception occurred, value: 4
Copyright ©2000-14 CRS Enterprises Ltd 95
assert Statements
def CalculateQuartile(percent): assert type(percent).__name__ == 'int' assert percent >= 0 and percent <= 100 quartile = 4 if percent > 25: quartile = 3 if percent > 50: quartile = 2 if percent > 75: quartile = 1 return quartile
def CalculateQuartile(percent): assert type(percent).__name__ == 'int' assert percent >= 0 and percent <= 100 quartile = 4 if percent > 25: quartile = 3 if percent > 50: quartile = 2 if percent > 75: quartile = 1 return quartile
print CalculateQuartile(34)print CalculateQuartile(104)
print CalculateQuartile(34)print CalculateQuartile(104)
2 assert percent >= 0 and percent <= 100AssertionError
2 assert percent >= 0 and percent <= 100AssertionError
Copyright ©2000-14 CRS Enterprises Ltd 97
Chapter 8
8
Copyright ©2000-14 CRS Enterprises Ltd 98
Classes and Objects
Classeswhat is a class
what is an object
Methodsdefining
calling
Attributesfor objects
for classes
Copyright ©2000-14 CRS Enterprises Ltd 99
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 100
A class definesa new data type
its operations
its state
Classes
{}
TackTack
bearingbearing
speedspeed
DropAnchorDropAnchor
Yacht
Operations
Attributes
Type
Copyright ©2000-14 CRS Enterprises Ltd 101
Classes
operationsmethods class Yacht:
def __init__(self, bearing, speed): self.bearing = bearing self.speed = speed
def Display(self): print self.bearing, self.speed
class Yacht: def __init__(self, bearing, speed): self.bearing = bearing self.speed = speed
def Display(self): print self.bearing, self.speed
reference to self
attributes
methods are functions
attributes are object references
Copyright ©2000-14 CRS Enterprises Ltd 102
Objects
A class is a blueprint for building objectsAn 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
class Yacht: def __init__(self, bearing, speed): self.bearing = bearing self.speed = speed
def Display(self): print self.bearing, self.speed
Object 1
bearing = 30speed = 1.3
Object 2
bearing = 40speed = 1.7
Copyright ©2000-14 CRS Enterprises Ltd 103
Creating ObjectsUse the classname to create a new object
returns an object reference
the object is not directly accessible
Object destroyed by the VMwhen no references exist
oceanis1 = Yacht()oceanis2 = Yacht()mirror1 = Yacht()mirror2 = Yacht()
oceanis1 = Yacht()oceanis2 = Yacht()mirror1 = Yacht()mirror2 = Yacht()
object reference
Copyright ©2000-14 CRS Enterprises Ltd 104
Initializing ObjectsClasses can define an __init__ method
method often takes parameters
defines how object will be initialized
only 1 initializer allowed
bearing = 25speed = 1.2
mirror1
mirror1 = Yacht(25, 1.2)mirror1 = Yacht(25, 1.2)def __init__(self, bearing, speed): self.bearing = bearing self.speed = speed
def __init__(self, bearing, speed): self.bearing = bearing self.speed = speed
Copyright ©2000-14 CRS Enterprises Ltd 105
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)
oceanis1.Display()oceanis2.Display()mirror1.Display()mirror2.Display()
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)
oceanis1.Display()oceanis2.Display()mirror1.Display()mirror2.Display()
25 1.235 6.090 3.5220 1.6
25 1.235 6.090 3.5220 1.6
Copyright ©2000-14 CRS Enterprises Ltd 106
Assigning ReferencesAssigning references
both point to the same object
bearing = 25speed = 1.2mirror2
mirror1
mirror1 = Yacht(25, 1.2)mirror2 = mirror1
mirror1 = Yacht(25, 1.2)mirror2 = mirror1
Copyright ©2000-14 CRS Enterprises Ltd 107
AttributesClass Attributes
shared by all objects in a class
Object Attributesunique to each object
Avoid name clashesobject attribute hides class attribute of the same name
Copyright ©2000-14 CRS Enterprises Ltd 108
Object AttributesObject attributes can be
defined on the flycan apply to different objectsObject b1 has
heightwidthcolor
Object b2 hasheightwidth
Use pass to define a empty classuseful for trying things out
class Box: pass
b1 = Box( )b2 = Box( )
b1.height = 100b1.width = 50b1.color = "red"
b2.height = 100b2.width = 50
class Box: pass
b1 = Box( )b2 = Box( )
b1.height = 100b1.width = 50b1.color = "red"
b2.height = 100b2.width = 50
Copyright ©2000-14 CRS Enterprises Ltd 109
Class AttributesShared by all objects in
class
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 %i,%i" % (id(self), self.x, self.y)
def MoveBy(self, dx, dy): self.x += dx self.y += dy
def HowManyPoints(self): print "There are %i Point object(s)\n" % Point.count
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 %i,%i" % (id(self), self.x, self.y)
def MoveBy(self, dx, dy): self.x += dx self.y += dy
def HowManyPoints(self): print "There are %i Point object(s)\n" % Point.count
class attribute
object attribute
normalmethod
static(class)method
Copyright ©2000-14 CRS Enterprises Ltd 110
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()
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()
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 ...
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 ...
Copyright ©2000-14 CRS Enterprises Ltd 111
Output from ExampleNote 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,7Point(23107068) is at 6,8There are 1 Point object(s)
Point(24318772) is at 15,17Point(24318772) is at 16,27There are 2 Point object(s)
Point(27787651) is at 25,27Point(27787651) is at 26,127There are 3 Point object(s)
Point(23107068) is at 5,7Point(23107068) is at 6,8There are 1 Point object(s)
Point(24318772) is at 15,17Point(24318772) is at 16,27There are 2 Point object(s)
Point(27787651) is at 25,27Point(27787651) is at 26,127There are 3 Point object(s)
Copyright ©2000-14 CRS Enterprises Ltd 113
Chapter 9
9
Copyright ©2000-14 CRS Enterprises Ltd 114
FilesOpening and closing
Reading and writing
Modesread only
read-write
append
Iterating through
Random Accessseek
Copyright ©2000-14 CRS Enterprises Ltd 115
File Objectsopen
creates a file object
closedestroys a file object
myFile = open('myfile.txt', 'w')myFile = open('myfile.txt', 'w')
myFile.close()myFile.close()
Copyright ©2000-14 CRS Enterprises Ltd 116
Iterating through a FileUse for-in statement
to process every line
loop terminates on end of file
f = open("hello.txt")for line in f: print line
f = open("hello.txt")for line in f: print line
Copyright ©2000-14 CRS Enterprises Ltd 117
Using with Statementwith statement
automatic clean up
avoid forgetting to close a file
generated codeinner try block will always close
but might throw an IOError
try: with open("data/hello.txt", "r") as f: for line in f: print line,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
try: f = open("data/hello.txt", "r") try: for line in f: print line, finally: f.close()except IOError,e: print e
try: f = open("data/hello.txt", "r") try: for line in f: print line, finally: f.close()except IOError,e: print e
generated code
Copyright ©2000-14 CRS Enterprises Ltd 118
Coping with ErrorsIf 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!" print error
try: f = open("data/unknown.txt", "r+t")except IOError,error: print "File open failed!" print error
error object
error class
Copyright ©2000-14 CRS Enterprises Ltd 119
Read MethodsSimple to read from files
f = open('myfile.txt', 'r')f.readline()f.readline()f.readline()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)
f = open('myfile.txt', 'w')data = f.read()f.close()
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', 'w')data = f.read(100)f.close()
read 100 bytes from file
Copyright ©2000-14 CRS Enterprises Ltd 120
Write MethodsSimple to write to files
sequence = ("line 1\n", "line 2\n", "line 3\n", "line 4\n")f = open("data/out2.txt", "w")f.writelines(sequence)f.close()
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
f = open("data/out1.txt", "w")f.write("line 1\nline 2\n")f.close()
f = open("data/out1.txt", "w")f.write("line 1\nline 2\n")f.close()
write a string
Copyright ©2000-14 CRS Enterprises Ltd 121
File Modesread only
use "r"
read and writeuse "r+"
or "w+" to empty file on opening
write onlyuse "w"
file will be empty on opening
appendinguse "a"
binaryuse "b" for binary and "t" for text (default)
random accesschoose appropriate mode and then use seek()
Copyright ©2000-14 CRS Enterprises Ltd 122
Writing Binary DataOpen file with mode 'b'
myFile = open('data/myfile2.bin', 'wb')myFile.write("\x5F\x9D\x3E");myFile.close()
myFile = open('data/myfile2.bin', 'wb')myFile.write("\x5F\x9D\x3E");myFile.close()
Copyright ©2000-14 CRS Enterprises Ltd 123
Reading Binary DataUse ord() and hex(ord()) for conversions
myFile = open('data/myfile2.bin', 'rb')
# read bytesch1 = myFile.read(1) # read 1 bytech2 = 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()
myFile = open('data/myfile2.bin', 'rb')
# read bytesch1 = myFile.read(1) # read 1 bytech2 = 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 124
Random Accessseek(offset, whence)
whence = 0 => from start of file
whence = 1 => from current position
whence = 2 => 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()
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 125
stdcodes = {}f = open("codes.txt", "r+t")
for line in f: [code, place] = line.rstrip().split(' ', 1) stdcodes[place] = code
placeRequested = raw_input("Enter place: ")try: print "The code for " + placeRequested + \ " is " + stdcodes[placeRequested]except KeyError: print "code not found"
stdcodes = {}f = open("codes.txt", "r+t")
for line in f: [code, place] = line.rstrip().split(' ', 1) stdcodes[place] = code
placeRequested = raw_input("Enter place: ")try: print "The code for " + placeRequested + \ " is " + stdcodes[placeRequested]except KeyError: print "code not found"
Reading a File into a DictionaryYou can read an entire file into a Dictionary
and then perform lookups
Town: WashingtonThe code for Washington is 0191
Town: WashingtonThe code for Washington is 0191
read a file line by line, splitting each line and then adding to dictionary
now try searching the dictionary
Copyright ©2000-14 CRS Enterprises Ltd 126
stdcodes = {}f = open("codes.txt", "r+t")
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]
stdcodes = {}f = open("codes.txt", "r+t")
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]
Sorting a File
read a file line by line, splitting each line and then adding to dictionary
extract the keys into an array then sort the array
now step through the sorted list looking up each entry in the original dictionary
Copyright ©2000-14 CRS Enterprises Ltd 129
Chapter 10
10
Copyright ©2000-14 CRS Enterprises Ltd 130
Larger Programs
Modules and Packages
Importing
Symbol Tables
Installing Libraries
Copyright ©2000-14 CRS Enterprises Ltd 131
Modules and PackagesPrograms can be organized into modules and packages
many modules are available in the Python and Java libraries
Modulesmay be Python code files
but can be written in other languages such as C/C++
Packagescollection of modules grouped using a common package name
helps resolve namespace conflicts
A package is defined by creating a directorywith 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 132
What is a ModuleImporting a file
executes all the code in that file
often just defines functions
import myfunctions
myfunctions.f1()myfunctions.f2()myfunctions.f3()myfunctions.f4()
import myfunctions
myfunctions.f1()myfunctions.f2()myfunctions.f3()myfunctions.f4()
def f1(): pass
def f2(): pass
def f3(): pass
def f4(): pass
def f1(): pass
def f2(): pass
def f3(): pass
def f4(): pass
myfunctions.py
Copyright ©2000-14 CRS Enterprises Ltd 133
Module Test CodeImporting 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
def f1(): passdef f2(): passdef f3(): passdef f4(): pass
if __name__ == "__main__": f1() f2() f3() f4()
def f1(): passdef f2(): passdef f3(): passdef f4(): pass
if __name__ == "__main__": f1() f2() f3() f4()
Copyright ©2000-14 CRS Enterprises Ltd 134
Importing4 ways to import
import mypackage.mysubpackage.MyClass as theClassx3 = theClass()x3.f3()
import mypackage.mysubpackage.MyClass as theClassx3 = theClass()x3.f3()
import mypackage.mysubpackage.MyClassx1 = mypackage.mysubpackage.MyClass()x1.f1()
import mypackage.mysubpackage.MyClassx1 = mypackage.mysubpackage.MyClass()x1.f1()
from mypackage import mysubpackagex2 = mysubpackage.MyClass()x2.f2()
from mypackage import mysubpackagex2 = mysubpackage.MyClass()x2.f2()
from mypackage.mysubpackage import MyClass as theClassx4 = theClass()x4.f4()
from mypackage.mysubpackage import MyClass as theClassx4 = theClass()x4.f4()
public class MyClass { public MyClass() { ... } public void f1() { ... } public void f2() { ... } public void f3() { ... } public void f4() { ... }}
public class MyClass { public MyClass() { ... } public void f1() { ... } public void f2() { ... } public void f3() { ... } public void f4() { ... }}
mypackage
mysubpackage
Copyright ©2000-14 CRS Enterprises Ltd 135
Packages
import syssys.path.append("lib")
# load both packages togetherimport mypackage.mysubpackage
x = mypackage.mysubpackage.ModuleA.A()x.f();x.g();x.h()
import syssys.path.append("lib")
# load both packages togetherimport mypackage.mysubpackage
x = mypackage.mysubpackage.ModuleA.A()x.f();x.g();x.h()
Import loads all modules together
executes __init__.py
for each package
loading mypackageloading mysubpackagethis is A.f() ...this is A.g() ...this is A.h() ...
loading mypackageloading mysubpackagethis is A.f() ...this is A.g() ...this is A.h() ...
mypackage/__init__.py
mysubpackage/__init__.py
ModuleA.py
Copyright ©2000-14 CRS Enterprises Ltd 136
Module Search PathWhen 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 syssys.path.append('mylib')
import syssys.path.append('mylib')
Copyright ©2000-14 CRS Enterprises Ltd 137
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 dictionarysymbols = dict(globals())
#print all the symbols in modulefor key, value in symbols.iteritems(): print key, value
# use globals to get a list of symbols in main module# Jython returns a StringMap which needs to be # converted to a dictionarysymbols = dict(globals())
#print all the symbols in modulefor key, value in symbols.iteritems(): print key, value
Copyright ©2000-14 CRS Enterprises Ltd 138
... Displaying Symbol TablesTo display symbol table of a module
use the module's dictionary
Iterate through the dictionary using iteritems()
#print all the symbols in myfunctions modulefor key, value in myfunctions.__dict__.iteritems(): print key, value
#print all the symbols in myfunctions modulefor key, value in myfunctions.__dict__.iteritems(): print key, value
Copyright ©2000-14 CRS Enterprises Ltd 139
Installing Third-Party LibrariesDefinitive 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 straightforwarduse 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 141
Chapter 11
11
Copyright ©2000-14 CRS Enterprises Ltd 142
Inheritance and Polymorphism
Inheritancenew style classes and object
subtyping
Abstract Classesinterfaces
OO contracts
Polymorphismthe good
the bad (duck typing)
Copyright ©2000-14 CRS Enterprises Ltd 143
SubclassingA 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 subclassis 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 144
The Object Class
All classes have a single rootobject
only for new style classes
Object defines methods inherited by all Python
classes
EmployeeEmployee
SalesPersonSalesPerson
PersonPerson
objectobject
Copyright ©2000-14 CRS Enterprises Ltd 145
ConstructorsSubclass 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 p = Person("Anne")e = Employee("Beth", 7468)s = SalesPerson("Carol", 4712, "NE")
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 p = Person("Anne")e = Employee("Beth", 7468)s = SalesPerson("Carol", 4712, "NE")
Employee IS A Person
SalesPerson IS A Employee
SalesPerson IS A Person
Copyright ©2000-14 CRS Enterprises Ltd 146
The Substitution RuleEmployee class
extends the Person class
SalesPerson classextends the Employee class
Employee substitutes forPerson object
SalesPerson substitutes forEmployee object
Person object
EmployeeEmployee
extends
SalesPersonSalesPerson
Superclass
Subclass
PersonPerson
extends
Copyright ©2000-14 CRS Enterprises Ltd 147
Inheriting Methodsclass Person(object): def Print( ): ...
class Person(object): def Print( ): ...
class Employee(Person): def GetBonus( ): ...
class Employee(Person): def GetBonus( ): ...
class Salesman(Employee): def GetBonus( ): ...
class Salesman(Employee): def GetBonus( ): ...Person p
Print( )
Employee e
Print( )
GetBonus( )
Salesman s
Print()
Employee.GetBonus( )Employee.GetBonus( )
GetBonus( )
Copyright ©2000-14 CRS Enterprises Ltd 148
Overriding Superclass MethodsSubclass can override any method of the superclass
superclass method hidden from client code
e = Employee("Beth", 7468)e.display()
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,
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 149
Concrete and Abstract ClassesConcrete class
all methods are fully implemented
may have instance variables
objects can be instantiated
Abstract classsome methods are not implemented
some methods are implemented
may have instance variables
objects cannot be instantiated
Hoistingabstract 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 150
from abc import ABCMeta, abstractmethod, abstractproperty
class Shape: __metaclass__ = ABCMeta
@abstractmethod def display(self): pass @abstractproperty def name(self): pass
from abc import ABCMeta, abstractmethod, abstractproperty
class Shape: __metaclass__ = ABCMeta
@abstractmethod def display(self): pass @abstractproperty def name(self): pass
Abstract Classes ...
Copyright ©2000-14 CRS Enterprises Ltd 151
... 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
class Circle(Shape): def __init__(self, name): self.theName = name def display(self): print "Circle", self.name @property def name(self): return self.theName must implement
all abstract methods
non abstract methods and instance variables automatically available
c = Circle("my-circle")print c.name c.display()
c = Circle("my-circle")print c.name c.display()
Copyright ©2000-14 CRS Enterprises Ltd 152
InterfacesAn 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 canimplemented multiple interfaces
multiple inheritance model
extend only one class
multiple inheritance model
Copyright ©2000-14 CRS Enterprises Ltd 153
Polymorphic MethodsAn (optional) abstract method
defined in interfaces and abstract classes
not appropriate for the superclass to provide an implementation
implemented by a subclasses
Implementationseach 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 154
PolymorphismPolymorphic 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 class SalesPerson(Employee): def Eat(self): pass def Drink(self): pass def Sleep(self): pass
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 class SalesPerson(Employee): 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()
def NightOut(p): p.Drink() p.Drink() p.Eat() p.Drink() p.Sleep()
Copyright ©2000-14 CRS Enterprises Ltd 155
Duck TypingPython allows polymorphic methods from classes not in
the hierarchynot really sensible
drawback of Python's weak (duck) typing
class Person(object): def Eat(self): pass def Drink(self): pass def Sleep(self): pass class Employee(Person): ...class SalesPerson(Employee): ...
class Person(object): def Eat(self): pass def Drink(self): pass def Sleep(self): pass class Employee(Person): ...class SalesPerson(Employee): ...
def NightOut(p): p.Drink() p.Drink() p.Eat() p.Drink() p.Sleep()
p = Person()e = Employee()s = SalesPerson()
NightOut(p)NightOut(e)NightOut(s)h = Horse()NightOut(h)
def NightOut(p): p.Drink() p.Drink() p.Eat() p.Drink() p.Sleep()
p = Person()e = Employee()s = SalesPerson()
NightOut(p)NightOut(e)NightOut(s)h = Horse()NightOut(h)
class Horse: def Eat(self): pass def Drink(self): pass def Sleep(self): pass
class Horse: def Eat(self): pass def Drink(self): pass def Sleep(self): pass
Copyright ©2000-14 CRS Enterprises Ltd 156
Interfaces as ContractsInterfaces for the Class Implementor
the interface defines all the methods and signatures for which the class designer must provide implementations
Interfaces for the Class Userthe class user can write code assuming that implementations will be
provided for all the methods in the interface
The Contracteach 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 159
Chapter 12
12
Copyright ©2000-14 CRS Enterprises Ltd 160
Further Topics
Intrinsic Attributesfor classes and objects
Dynamic Statementsexec and eval
Operator Overloadingnumeric typeslist types
Copyright ©2000-14 CRS Enterprises Ltd 161
The 5 Intrinsic Class Attributes__name__ name of the class (read only)
__doc__ class documentation string
__module__ module in which the class is defined
__dict__ map of all class attributes
__bases__ 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__
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__
DerivedThis is the Derived class__main__{'Display': <function Display at ... (<class __main__.Base at ...
DerivedThis is the Derived class__main__{'Display': <function Display at ... (<class __main__.Base at ...
Copyright ©2000-14 CRS Enterprises Ltd 162
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 = 10print x.__class__print x.__dict__
class Derived(Base): "This is the Derived class" def Display(self): pass
x = Derived()x.color = "red"x.width = 10print x.__class__print x.__dict__
__main__.Derived{'color': 'red', 'width': 10}
__main__.Derived{'color': 'red', 'width': 10}
Copyright ©2000-14 CRS Enterprises Ltd 163
exec and eval Statements
x = 10y = 20codeFragment = raw_input("Please enter some code (e.g. 'print x + y'): ")exec codeFragment
x = 10y = 20codeFragment = 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 + 1201
Please enter some code (e.g. 'print x + y'): print x * y + 1201
x = 10y = 20codeFragment = str(input("Please enter an expression (e.g. 'x + y'): "))result = eval(codeFragment)print "result is: ", result
x = 10y = 20codeFragment = 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 * yresult is: 200
Please enter an expression (e.g. 'x + y'): x * yresult is: 200
exec
eval
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 __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) def Display(self): print "Time is", self.hrs, self.min
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) def Display(self): print "Time is", self.hrs, self.min
t3 = t1 + t2t3 = t1 + t2
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 __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 def Display(self): print "Time is", self.hrs, self.min
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 def Display(self): print "Time is", self.hrs, self.min
t1 += t3t1 += t3
Copyright ©2000-14 CRS Enterprises Ltd 166
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)
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 def Display(self): print "Time is", self.hrs, self.min
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)
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 def Display(self): print "Time is", self.hrs, self.min
t1 = Time(5,30)t2 = Time(3,30)t3 = t1 + t2t3.Display()
t1 += t3t1.Display()
t1 = Time(5,30)t2 = Time(3,30)t3 = t1 + t2t3.Display()
t1 += t3t1.Display()
Time is 9 0Time is 9 0
Time is 14 30Time is 14 30
Copyright ©2000-14 CRS Enterprises Ltd 167
Operator Overloading other TypesEmulate other types
Built-In Objects
Sequences
Slices
Emulate Maps
Special Methods to be Writtene.g. for Maps
__len__(self)
__getitem__(self,key)
__setitem__(self,key,value)
__delitem__(self,key)
Copyright ©2000-14 CRS Enterprises Ltd 168
Operator Overloading List Types
class MyList: def __init__(self, p1, p2): self.theList = [ ] self.theList.append(p1) self.theList.append(p2) def __add__(self, other): result = [ ] for item in self.theList: result.append(item) for item in other.theList: result.append(item) return result
class MyList: def __init__(self, p1, p2): self.theList = [ ] self.theList.append(p1) self.theList.append(p2) def __add__(self, other): result = [ ] for item in self.theList: result.append(item) for item in other.theList: result.append(item) return result
t1 = MyList(1,2)t2 = MyList(3,4)t3 = t1 + t2
t1 = MyList(1,2)t2 = MyList(3,4)t3 = t1 + t2
t1: [1,2]t2: [3,4]t3: [1,2,3,4]
t1: [1,2]t2: [3,4]t3: [1,2,3,4]
Copyright ©2000-14 CRS Enterprises Ltd 169
Overloading [ ] using __getitem__
class mydata: def __init__(self): self.data = "ABCDEFG" def __getitem__(self, i): return self.data[i]
object = mydata()
theChar = object[1]print theChar;
for item in object: print item,
class mydata: def __init__(self): self.data = "ABCDEFG" def __getitem__(self, i): return self.data[i]
object = mydata()
theChar = object[1]print theChar;
for item in object: print item,
BA B C D E F G
BA B C D E F G
Copyright ©2000-14 CRS Enterprises Ltd 171
Chapter 13
13
Copyright ©2000-14 CRS Enterprises Ltd 172
Pattern MatchingPattern Matching
Splitting
Substitution
Comments
Replacement
Capture Patterns
Greedy Matching
Look Ahead
Copyright ©2000-14 CRS Enterprises Ltd 173
Anchors and Selectionsselection 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 174
Repeat Countsrepeat 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 or more vowels[0-9]+ 1 or more digits (\d+)[0-9]{3,5} 3 to 5 digits\.? 0 or 1 periods
[aeiou]* 0 or more vowels[0-9]+ 1 or more digits (\d+)[0-9]{3,5} 3 to 5 digits\.? 0 or 1 periods
\. matches a periodthe backslash negates the special meaning of the pattern that follows
Copyright ©2000-14 CRS Enterprises Ltd 175
Pattern Matching Functionsmatch
match from the start of text
searchmatch anywhere in the text
import re
test = "-------ABC------------"pattern = r"\w+"pattern = re.compile(pattern)
match = pattern.match(test)print match
match = pattern.search(test)print match.group()
import re
test = "-------ABC------------"pattern = r"\w+"pattern = re.compile(pattern)
match = pattern.match(test)print match
match = pattern.search(test)print match.group()
None
ABC
None
ABC
Copyright ©2000-14 CRS Enterprises Ltd 176
['aaa', 'bbb', 'ccc', 'ddd', 'eee']['aaa', 'bbb', 'ccc', 'ddd', 'eee']
SplittingPerhaps we want to split a string using a regular
expression as a delimiterpattern.split(text)
import re
pattern = re.compile(r"\s*;\s*")text = "aaa ; bbb ;ccc ; ddd ; eee"list = pattern.split(text)print list
import re
pattern = re.compile(r"\s*;\s*")text = "aaa ; bbb ;ccc ; ddd ; eee"list = pattern.split(text)print list
Copyright ©2000-14 CRS Enterprises Ltd 177
aaa---bbb---ccc---ddd---eeeaaa---bbb---ccc---ddd---eee
SubstitutionPerhaps 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
import re
pattern = re.compile(r"\s*;\s*")text = "aaa ; bbb ;ccc ; ddd ; eee"newText = pattern.sub("---", text)print newText
Copyright ©2000-14 CRS Enterprises Ltd 178
Using CommentsAlways a good idea to use comments
regular expressions are difficult to read at the best of times
import restring = "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)
import restring = "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 179
More Advanced SearchesUse ( ) in pattern to capture data
import re
text = "---111122223333333333334444555566667777---"pattern = "2+(3+)4+(5+)6+"
# search for patternpattern = re.compile(pattern)result = pattern.search(text)
# print resultsprint "full match: ", result.group(0)print "capture pattern 1: ", result.group(1)print "capture pattern 2: ", result.group(2)print "all captures: ", result.groups()
import re
text = "---111122223333333333334444555566667777---"pattern = "2+(3+)4+(5+)6+"
# search for patternpattern = re.compile(pattern)result = pattern.search(text)
# print resultsprint "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 180
Repeating PatternsUse findall() and finditer()
to repeat searches
import re
text = "AB12CD34EF56GH"pattern = r"(\d+)"
# find all occurrences of patternmatcher = re.findall(pattern, text)print matcher
# iterate through finding the patternfor matcher in re.finditer(pattern, text): print matcher.groups(0)
import re
text = "AB12CD34EF56GH"pattern = r"(\d+)"
# find all occurrences of patternmatcher = re.findall(pattern, text)print matcher
# iterate through finding the patternfor matcher in re.finditer(pattern, text): print matcher.groups(0)
['12', '34', '56']
('12',)('34',)('56',)
['12', '34', '56']
('12',)('34',)('56',)
Copyright ©2000-14 CRS Enterprises Ltd 181
Greedy PatternsGreedy Patterns are the default
Use ? to use non greedy matching
text = "AAAA1111BBBB2222CCCC3333DDDD"greedyPattern = r"^(.+)(\d+)(.+)$"nonGreedyPattern = r"^(.+?)(\d+)(.+)$"
text = "AAAA1111BBBB2222CCCC3333DDDD"greedyPattern = r"^(.+)(\d+)(.+)$"nonGreedyPattern = r"^(.+?)(\d+)(.+)$"
^(.+)(\d+)(.+)$Greedy: <AAAA1111BBBB2222CCCC333><3><DDDD>^(.+?)(\d+)(.+)$Non-Greedy: <AAAA><1111><BBBB2222CCCC3333DDDD>
^(.+)(\d+)(.+)$Greedy: <AAAA1111BBBB2222CCCC333><3><DDDD>^(.+?)(\d+)(.+)$Non-Greedy: <AAAA><1111><BBBB2222CCCC3333DDDD>
Copyright ©2000-14 CRS Enterprises Ltd 182
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+$\w+[.](?!bat)\w+$
filename.ext
not "bat"?!bat
Copyright ©2000-14 CRS Enterprises Ltd 183
Building PatternsTranslation 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: ", patterntext = '''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
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: ", patterntext = '''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 184
Copyright ©2000-14 CRS Enterprises Ltd 185
Chapter 14
14
Copyright ©2000-14 CRS Enterprises Ltd 186
Unit TestUnittest framework
DocTest
PyTest
Copyright ©2000-14 CRS Enterprises Ltd 187
Components of Unittesttest fixture
code run to prepare for one or more tests
e.g. start a server
any associate cleanup actions
test caseunit of testing
implemented as a method of test class
test suitea collection of test cases
used to aggregate tests that should be executed together.
test runnercomponent which orchestrates the execution of tests
provides output relating to the success or failure of the tests
Copyright ©2000-14 CRS Enterprises Ltd 188
Structure of Test Classderive from unittest.TestCase
setUp call before each test
tearDown called after each test
execute tests by callingunittest.main()
test names must begin withtest...
import unittest
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()
import unittest
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 189
Structure of a Test CaseUse 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")
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'
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 190
Test FunctionsassertEqual()
check for an expected result
assert_()verify a condition
assertRaises()verify that an expected exception gets raised
Copyright ©2000-14 CRS Enterprises Ltd 191
Test SuitesTests can be grouped into suites
def suite(): suite = unittest.TestSuite() suite.addTest(testPoint('testConstructor')) suite.addTest(testPoint('testMoveBy1')) suite.addTest(testPoint('testDistance1')) return suite
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)
if __name__ == '__main__': mySuite = suite() unittest.TextTestRunner(verbosity=0).run(mySuite)
Copyright ©2000-14 CRS Enterprises Ltd 192
DocTestDocTest module searches for text that look like
interactive Python sessionsexecutes those sessions to verify that they work exactly as shown
Tests are embedded in codeeasy to define tests
can cause clutter
Copyright ©2000-14 CRS Enterprises Ltd 193
01 simple exampleUse doctest.testmod(...)
many parameters, but usually just use verbose=True
if __name__ == '__main__': import doctest doctest.testmod(verbose = True)
if __name__ == '__main__': import doctest doctest.testmod(verbose = True)
def cube(x): """ The cube function returns x * x * x >>> cube(3) 27 >>> cube(-1) -1 """ return x*x*x
def cube(x): """ The cube function returns x * x * x >>> cube(3) 27 >>> cube(-1) -1 """ return x*x*x
Copyright ©2000-14 CRS Enterprises Ltd 194
02 formattingTests 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
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 195
03 failuresFailures reported
with line numbers
and erroneous result
Trying: sumsquares( 4 )Expecting: 30457**********************************************************************File "C:\_Eclipse\Advanced Python\src\Unit Test FrameworkFailed example: sumsquares( 4 )Expected: 30457Got: 30
Trying: sumsquares( 4 )Expecting: 30457**********************************************************************File "C:\_Eclipse\Advanced Python\src\Unit Test FrameworkFailed example: sumsquares( 4 )Expected: 30457Got: 30
def sumsquares(n): """ 1+4+9+16 = 30 (not 30457) >>> sumsquares( 4 ) 30457 """ sum = 0 for i in range(n+1): sum += square(i) return sum
def sumsquares(n): """ 1+4+9+16 = 30 (not 30457) >>> sumsquares( 4 ) 30457 """ sum = 0 for i in range(n+1): sum += square(i) return sum
Copyright ©2000-14 CRS Enterprises Ltd 196
04 exceptionsExceptions 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
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 197
PyTestPyTest 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 198
01 simple exampleAdd 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
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 199
02 multiple testsUse iterators to create multiple tests
Use setup_class()for initial test conditions
class TestSquare: 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
class TestSquare: 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
Recommended