Copyright ©2000-14 CRS Enterprises Ltd 1 Python Fundamentals by Chris Seddon

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,

print

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,

print

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