OOP Workbook
OOP Workbook
Object-Oriented
Programming
In Python
Workbook
Damian Gordon
2020
Feel free to use any of the content in the guide with my permission.
1
Object-Oriented Programming
Table of Contents
1. Object-Oriented Design
2. Objects in Python
5. Object-Oriented Programs
6. String Formatting
7. Regular Expressions
8. Object Serialization
9. Design Patterns
2
Object-Oriented Programming
Object-Oriented Design
What is a Class?
Creating a Class is like creating a variable, it’s just a definition of a data type until it gets
assigned a value, once you have an instance of a Class, we call it an Object. If our class is
“Dog”, we could have objects “Tiny”, “Rover”, “Rusty”, and “Fido”.
What is an Object?
An object has: • Attributes (or Features) are a collection of variables.
Attributes and Methods • Methods (or Behaviours) are a collection of functions.
• The Attributes and Methods are encapsulated or
contained in the object.
• The object can be configured so that some Attributes
and Methods are private to the object, and others are
visible to other objects, this is Information Hiding.
• The public elements (Attributes and Methods) of the
class are referred to as the Interface (or Public
Interface).
Object-Oriented Concepts
Abstraction Inheritance
Abstraction means dealing with the Inheritance means that one class can inherit
level of detail that is most appropriate attributes and methods from another class. So
to a given task. For example, a driver we look for classes that have a lot in common,
and a mechanic interact with a car at and create a single class with those
different levels of abstraction. commonalities.
Composition Polymorphism
Composition means collecting several Polymorphism is the ability to treat a class
objects together to create a new one. It differently depending on which subclass is
is usually a good choice when one implemented. The appropriate subclass is
object is part of another object. determined based on parameters passed in.
We’ll look at these concepts in more detail later.
Object Oriented Programming © Damian Gordon
3
Object-Oriented Programming
Object-Oriented Design
Class Diagrams
A Class Diagram shows the design of a system showing the classes, and their attributes
and methods. It also shows the relationship between classes, with a line (association)
between classes, with a verb to describe the relationship, and cardinality is indicated by
numbers, in this case 1…* indicates a one-to-many relationship.
4
Object-Oriented Programming
Objects in Python
We remember, that an object has
Methods and Attributes:
5
Object-Oriented Programming
Objects in Python
The Initialization Method
Sometimes when a developer creates a new class they forget to declare all of the
attributes required, or forget to give those attributes a starting value (“initial value”). So
Python has a special method called “_ _init_ _( )” which forces the developer to
make sure they declare and initialize all of the attributes that are required by each
program. It can also be declared in such a way as to set default values for all attributes.
The Initialization method should be used in every class unless there is a very good reason.
Docstrings
One of the key motivations behind the object-oriented paradigm is the idea of “code
reuse”, so if you (or someone else) have already written a method or class, if it is at all
possible you should not rewrite the code again. Good documentation and labelling are an
important element of making the purpose and intent of programs clear. One feature that
Python provides to make this easier is the Doscstring feature, where you can add
descriptive sentence to each class and method, as the first line of that class or method.
class Point:
“Represents a point in 2D space”
def move(self,a,b):
‘Move the point to a new location’
self.x = a
self.y = b
# END Move
# END Class
In the Python shell, all you need to do is type “help” with the name of the class in
brackets, and you will see all the Docstrings.
>>> help (Point)
So the purpose of all of the methods is made clear using the HELP command.
6
Object-Oriented Programming
import <Filename>
• To use specific class from a program (module) in the same folder, we can say:
• If there already is a class in the calling program as the name of the class we want
to import, we can import it with an alias:
• If we want to import all the classes (which isn’t really a good idea), we can say:
PACKAGES
• If we feel there are too many programs (modules) in the current folder, we can
create a sub-folder (package) to put some in that. Then to make it possible to
access the programs in that subfolder we need to add a blank textfile into the
subfolder called the following:
_ _init_ _.py
o import <SubFolder>.<Filename>
7
Object-Oriented Programming
We can put text in the _ _init_ _.py file to import code directly from a package as
opposed to a module.
The “global” command allows us to create a global variable, and we can make changes
to that variable in a local context.
If we want to check if a program is being called from another program, or is being run
as a stand-alone program, we can say:
if _ _name_ _ == “_ _main_ _”:
We can also add a comment in the docstrings at the start of the class indicating which
methods or attributes are for internal use only.
Third-Party Libraries
Python comes with a very big Standard Library with lots of features, but we may be
looking for a feature that it doesn’t have, if so we have two options; we can write a new
package ourselves, or we can use somebody else’s code.
If we want to find packages that might be of use, we can use the Python Package Index
(PyPI) website: http://pypi.python.org.
Once we’ve found a package that we want to install, we can use the pip tool to install it.
Pip doesn’t come with the Python download, but we can download it from here:
https://pypi.python.org/pypi/pip
And once pip has been installed, we can install the software into our library using:
• pip install <package>
8
Object-Oriented Programming
9
Object-Oriented Programming
Because the method order exists only in the class Supplier, not in Contact.
Super is a function, typically called as super(), that allows a subclass to call a method
in a superclass, by saying super().SuperclassMethod.
Multiple Inheritance
A subclass can inherit for more than one superclass in a very simple way:
class Subclass(Superclass1, Superclass2):
<Class Declaration>
# END Class.
In this scenario, when a specific attribute or method is mentioned, the Python interpreter
first looks for it in the current class, and if it isn’t there the interpreter will check the first
superclass for the attribute or method, and if it isn’t found there the interpreter will
check if that superclass itself has a superclass, if so it will check that one, if not it will
move onto the second superclass (this is called a depth-first search).
Polymorphism
Polymorphism means that we can call the same method name with different parameters,
and depending on the parameters, it will do different things. For example:
10
Object-Oriented Programming
Object-Oriented Programs
Moving from Procedural to Object-Oriented Programs
One of the key goals of object-oriented programming is software reuse. To achieve this
we wrap methods and attributes in a class, and that makes it easier for other programs
to use those classes. If we are just modelling data, maybe an array is all we need, and if
we are just modelling behaviours, maybe some methods are all we need; but if we are
modelling both data and behaviours, an object-oriented approach makes sense.
In this example we are calculating the perimeter of a shape. The code in black is the
procedural version of the program, and the code in red is what we need to add in to
make it object-oriented. We need to add in an init method for each class, and we also
need to add in a method to take point values into the class, because with object-oriented
design we prefer to encapsulate the values, and change them through a method.
# PROGRAM CalculatePerimeter:
import math
class Point:
def _ _init_ _(self, x, y):
self.x = x
self.y = y
# END init
class Polygon:
def _ _init_ _(self):
self.vertices = []
# END init
def perimeter(self):
perimeter = 0
points = self.vertices + [self.vertices[0]]
for i in range(len(self.vertices)):
perimeter += points[i].distance(points[i+1])
# ENDFOR
return perimeter
# END perimeter
# END.
The object-oriented code in red, doubles the length of the program.
/
11
Object-Oriented Programming
Object-Oriented Programs
Running the Program
Below is how we would run the program procedurally, and how we would run it in an
object-oriented way. As we can see in the procedural version we input the perimeter
points directly, whereas in the object-oriented version we input them via a method. The
object-oriented version certainly isn’t more compact than the procedural version, but it is
much clearer in terms of what is happening, and makes reuse far easier.
Procedural Version Object-Oriented Version
>>> square = >>> square = Polygon()
[(1,1),(1,2),(2,2),(2,1)] >>> square.add_point(Point(1,1))
>>> square.add_point(Point(1,2))
>>> perimeter(square) >>> square.add_point(Point(2,2))
>>> square.add_point(Point(2,1))
>>> print(square.perimeter())
_____________________________ _________________________________________
Getters and Setters
As we mentioned, we prefer to access attributes through methods instead of accessing
them directly.There are times when that applies to the internal code as well as to other
classes. For example, if we want to assign a variable called name to a particular value, we
would say something like Colour.name = “Red”, but, we could also write a method
as follows, and to assign a value we would say Colour.set_name(“Red”).
def set_name(self, name):
self._name = name
# END set_name.
We can do the same for the command print(Colour.name) which we can change
to become print(Colour.get_name() [We can do the same for a return]:
def get_name(self):
return self._name
# END get_name.
The real benefit of getters and setters is that we can add conditions and checking into the
getters and setters to make the code more robust and powerful:
def get_name(self):
if self._name == "":
return "There is a blank value"
else:
return self._name
# ENDIF;
# END get_name.
If we have code that already does assignments and prints, we can force them to run as
getters and setters using the property function as follows:
>>> name = property(_get_name, _set_name)
And now without having to change any code, the assignments, prints, and returns are
upgraded to become getters (aka accessor methods) and setters (aka mutator methods).
Manager Objects
Manager Objects are like managers in offices, they tell other people what to do. The
manager class and objects don’t really do much activity themselves, and instead they call
other methods, and pass messages between those methods.
.
Object Oriented Programming © Damian Gordon
12
Object-Oriented Programming
String Formatting
String Declarations
There are a lot of different ways to declare a string in Python, you can use a set of double
quotes (“) or a set of single quotes (‘). You can also create a string be enclosing a number
of strings in round brackets (generators). To declare a sting over multiple lines all you
have to do is enclose the strings in three double quotes (“) or three single quotes (‘).
s = "Hello World“
s.count('o‘) # How often does ‘o’ appear in s? 2 (‘o’ appears twice)
s.count(‘l‘) # How often does ‘l’ appear in s? 3 (‘l’ appears three times)
s.find('o‘) # What position is the first ‘o’ at? 4 (starting at location zero)
s.find(‘l‘) # What position is the first ‘l’ at? 2 (starting at location zero)
s.rfind('o‘) # What position is the last ‘o’ at? 7 (starting at location zero)
s.rfind(‘l‘) # What position is the last ‘l’ at? 9 (starting at location zero)
String Manipulation
Other built-in methods include the split method to split a string based on a specificed
parameter, the join method join substrings based on a specificed parameter, the
replace method replaces characters in a string with others, the partition method
divides the string into three parts based on the first occurance of a specificed parameter,
and finally the rpartition method splits on the last occurance of a parameter.
13
Object-Oriented Programming
String Formatting
The format Method
Another built-in method that Python 3 provides is the format method. This allows you
to add text into a string using curly braces. There are a number of different ways of
persenting the arguments to the string.
Unindexed Arguments
If you put empty curly braces into the string with and have an equivalent number of
strings in the format command, Python will use positional substitution to repleace the
first set of braces with the first string in the format command, the second braces with
with the second string in the format command, etc.
MyText = "{}, you are currently {}"
print(MyText.format('Damian', 'teaching'))
Gives you the following output:
Damian, you are currently teaching
Indexed Arguments
If you put numbers in the curly braces and have a number of strings in the format
command, the Python intrepreter will substitute the arguments on the basis of the
numbers (starting at zero).
MyText = "{0}, you are currently {1}, thanks {0}"
print(MyText.format('Damian', 'teaching'))
Gives you the following output:
Damian, you are currently teaching, thanks Damian
Keywords Arguments
If you put labels in the curly braces and have a number of strings, each associated with
one of the labels, in the format command, the Python intrepreter will substitute the
arguments on the basis of the labels.
MyText = "{name}, you are currently {activity}"
print(MyText.format(name=”Damian”, activity=”teaching”))
Gives you the following output:
Damian, you are currently teaching
This is a sampling of the range of ways you can use string arguments.
14
Object-Oriented Programming
Regular Expressions
Regular Expressions
A regular expression is a sequence of characters that define a search pattern, mainly for
use in pattern matching with strings, or string matching. Regular expressions originated
in 1956, when mathematician Stephen Cole Kleene described regular languages using his
mathematical notation called regular sets. Python has a library called re to help:
# PROGRAM MatchingPatterns:
import re
SearchString = "hello world"
pattern = "hello world"
IsMatch = re.match(pattern, SearchString)
if IsMatch == True:
print("regex matches")
# ENDIF;
# END.
This program compares SearchString to pattern, and if it matchs, it prints out the
phrase “regex matches”.
Basic Patterns Basic Pattern Matching
'hello world' matches 'hello world'
Logical OR: A vertical bar separates 'hello world' matches 'hello worl'
alternatives. For example, gray|grey can 'hello world' does not matche 'ello world'
match "gray" or "grey".
Grouping: Parentheses are used to Matching Single Characters
define the scope and precedence of the 'hello world' matches 'hel.o world'
operators. For example, gr(a|e)y 'helpo world' matches 'hel.o world'
'hel o world' matches 'hel.o world'
'helo world' does not match 'hel.o world'
?: indicates zero or one occurrences of
'hello world' matches 'hel[lp]o world'
the preceding element. For example, 'helpo world' matches 'hel[lp]o world'
colou?r matches both "color" and 'helPo world' does not match 'hel[lp]o world'
"colour". 'hello world' does not match 'hello [a-z] world'
*: indicates zero or more occurrences of 'hello b world' matches 'hello [a-z] world'
the preceding element. For example, 'hello B world' matches 'hello [a-zA-Z] world'
ab*c matches "ac", "abc", "abbc", 'hello 2 world' matches 'hello [a-zA-Z0-9] world'
"abbbc", and so on.
+: indicates one or more occurrences of Special Characters
the preceding element. For example, '.' matches pattern '\.'
ab+c matches "abc", "abbc", "abbbc", ‘[' matches pattern '\['
and so on, but not "ac". ‘]' matches pattern '\]‘
‘(' matches pattern '\(‘
‘)' matches pattern '\)‘
{n}: The preceding item is matched
exactly n times.
Example Matches
{min,}: The preceding item is matched
'(abc]' matches '\(abc\]'
min or more times.
' 1a' matches '\s\d\w'
{min,max}: The preceding item is '\t5n' does not match '\s\d\w'
matched at least min times, but not ' 5n' matches '\s\d\w'
more than max times.
15
Object-Oriented Programming
Regular Expressions
Matching Multiple Characters More Complex Patterns
Combining the patterns together allows us
The asterisk (*) character says that the to expand our pattern-matching repertoire:
previous character can be matched zero 'Eat.' matches
or more times. '[A-Z][a-z]*( [a-z]+)*\.$'
'hello' matches 'hel*o' 'Eat more good food.' matches
'heo' matches 'hel*o' '[A-Z][a-z]*( [a-z]+)*\.$'
'helllllo' matches 'hel*o' 'A good meal.' matches
'[A-Z][a-z]*( [a-z]+)*\.$'
The pattern [a-z]* matches any
collection of lowercase words, including RegEx for a Valid e-mail Format
the empty string: The regular expression that can be used to
'A string.' matches '[A-Z][a-z]* [a-z]*\.' represent a valid e-mail is as follows:
'No .' matches '[A-Z][a-z]* [a-z]*\.' pattern = "^[a-zA-Z.]+@([a-z.]*\.[a-z]+)$"
'' matches '[a-z]*.*'
More re Methods
The plus (+) sign in a pattern behaves In addition to the match function, the re
similarly to an asterisk; it states that the module provides a couple other useful
previous character can be repeated one functions, search(), and findall().
or more times, but, unlike the asterisk is • The search() function finds the
not optional: first instance of a matching pattern,
'0.4' matches '\d+\.\d+' relaxing the restriction that the
'1.002' matches '\d+\.\d+' pattern start at the first letter.
'1.' does not match '\d+\.\d+' • The findall()function behaves
similarly to search, except that it
The question mark (?) ensures a finds all non-overlapping instances
character shows up exactly zero or of the matching pattern, not just the
one times, but not more. first one.
'1%' matches '\d?\d%' >>> import re
'99%' matches '\d?\d%'
'999%' does not match '\d?\d%' >>> re.findall('a.', 'abacadefagah')
['ab', 'ac', 'ad', 'ag', 'ah']
If we want to check for a repeating
sequence of characters, by enclosing any >>> re.findall('a(.)', 'abacadefagah')
set of characters in parenthesis, we can ['b', 'c', 'd', 'g', 'h']
treat them as a single pattern:
'abccc' matches 'abc{3}' >>> re.findall('(a)(.)', 'abacadefagah')
'abccc' does not match '(abc){3}' [('a', 'b'), ('a', 'c'), ('a', 'd'), ('a', 'g'), ('a', 'h')]
'abcabcabc' matches '(abc){3}'
>>> re.findall('((a)(.))', 'abacadefagah')
Two Further Patterns [('ab', 'a', 'b'), ('ac', 'a', 'c'), ('ad', 'a', 'd'),
^: The start of a string. ('ag', 'a', 'g'), ('ah', 'a', 'h')]
$: The end of a string.
16
Object-Oriented Programming
Object Serialization
Serializing and Deserializing (Pickling andUnpickling)
We can store an object into a file, and retrieving it later from storage. Storing an object is
called serializing it, and retrieving it is called deserializing it. Python uses a function called
pickle to do this. So sometimes instead of saying we are serializing an object, we can
say we are pickling an object; and instead of deserializing an object, we can say we are
unpickling an object.
Example Program
import pickle
MyObject = ["a list", "containing", 5, "values including
another list", ["inner", "list"]]
17
Object-Oriented Programming
Object Serialization
Serializing Web Objects
To transmit object data over the web you need to use a recognised standard so that the
sending and receiving classes will know what is being transmitted. There are many
common standards, but the most common one is JSON (“jason”). JSON stands for
JavaScript Object Notation, and is an open-standard format that uses human-readable
text to transmit data objects consisting of attribute–value pairs. JSON is a language-
independent data format, and the JSON filename extension is .json:
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York"
}
}
18
Object-Oriented Programming
Design Patterns
What are Design Patterns?
Computer scientists got together and discussed the common types of problems they are
usually asked to solve, and realised that a lot ofcreated a set of generic solutions to those
problem. These are not full programs, and sometimes not even pseudocode, but
represent good ideas or good approaches to solving common problems. Types of Design
Patterns include: Algorithm strategy patterns, Computational design patterns,
Execution patterns, Implementation strategy patterns, and Structural design patterns
Some Common Design Patterns
The Iterator Pattern: A design pattern in which an iterator is used to traverse a
container and access the container's elements.
The Decorator Pattern: A design pattern which wraps an existing class and can alter
the functionality of the methods.
The Observer Pattern: A design pattern which monitors a core class and different
observers react different to changes in the core class.
The Strategy Pattern: A design pattern which presents different potential solutions to
the same problem, and allows the program to choose the most suitable one.
The State Pattern: A design pattern which represents a system that goes through
different states, and records the current state and the transitions between states.
The Singleton Pattern: A design pattern which allows only one object based on a
certain class to exist.
The Template Pattern: A design pattern which creates a common base class the can
be inherited by multiple class that share common states, these can override the base
class methods.
The Adapter Pattern: A design pattern which allows two pre-existing objects to
interact with each other, even if their interfaces are not compatible.
The Façade Pattern: A design pattern which presents a simple interface to complex
system but encapsulating typical usage into a new object.
The Flyweight Pattern: A design pattern which helps objects that share the same
state to use the same memory location.
The Command Pattern: A design pattern which creates an object (an execute object)
that can execute another object at a later time.
The Abstract Factory Pattern: A design pattern which returns a different class (or
implementation) of the same system, depending on the platform, local settings, or
current locale.
The Composite Pattern: A design pattern which allows complex tree-like structures to
be built easily from simple components.
These are some of the 23 classic design patterns.
19
Object-Oriented Programming
Design Patterns
The Singleton Pattern
The Singleton Pattern is a design pattern which allows only one object based on a certain
class to exist. The general Singleton design pattern is as follows:
class Singleton:
IsSingleton = None
Method NewObject:
If IsSingleton == None
Then IsSingleton = super(Singleton).new_object
EndIf;
return IsSingleton
# END NewObject
# END Singleton.
# END OneOnly.
In Python we use the _ _new_ _ class to help ensure there’s only one instance of a class.
When the _ _new_ _ class is called, it typically creates a new instance of that class. When
we override it, we first check if our singleton instance has been created; if not, we create
it using a super() call.
20
Object-Oriented Programming
Design Patterns
The Iterator Pattern
The iterator pattern is a design pattern in which an iterator is used to traverse a
container and access the container's elements. Contaier types include lists, tuples,
dictionaries, and sets, and they can be structured in multiple ways:
def __iter__(self):
return ITERATOR(self.VALUE)
# END Iter
# END ITERABLE.
class ITERATOR:
def __init__(self, VALUE):
self.VALUE = VALUE
self.index = 0
# END Init
def __iter__(self):
return self
# END Iter
def __next__(self):
if CONDITION:
VALUE = SELF.VALUE
self.index = self.index + 1
return VALUE
else:
raise StopIteration()
# ENDIF;
# END Next
# END ITERATOR.
This is the general design pattern, not the specific implementation.
21
Object-Oriented Programming
Design Patterns
Python Iterator Pattern
To implement the Iterator Pattern, Python provides you with a pair of built-ins:
• iter() takes in a container object and builds and returns a new iterator object.
• next() takes in the iterator and, each time it is called, returns the next item
from the container.When there are no more objects to return, the exception
StopIteration is raised.
class MyCountIterable:
def __init__(self, Value):
self.Value = Value
# END Init
def __iter__(self):
return MyCountIteration(self.Value)
# END Iter
# END MyCountIterable.
class MyCountIteration:
def __init__(self, Value):
self.Index = 0
self.Value = Value
# END Init
def __iter__(self):
# Iterators are iterables too.
return self
# END Iter
def __next__(self):
if self.Index < self.Value:
# THEN
Index = self.Index
self.Index += 1
return Index
else:
raise StopIteration()
# ENDIF;
# END Next
# END MyCountIteration.
22
Object-Oriented Programming
List Comprehensions
Let’s imagine we had a list (or array) of strings, as follows:
• string_array = [“234", "75", "331", "73", "5"]
If we wanted to take each element and covert them into integers, we could do:
Output1 = [int(num) for num in string_array]
\________/ \______________________/
Convert num to integer for each number in the list
Which would give us:
[234, 75, 331, 73, 5]
Set Comprehensions
A set is like a list but with no duplicate entries. We create a set is to use the set()
constructor to convert a list into a set, but we can also use a set comprehension.
f-authors = {b.author for b in books if b.genre == 'fantasy'}
\______/ \_____________/ \_______________________/
Add unique author for each book in list if genre attribute is “fantasy”
Which would give us the following output (removing any duplicate values):
{'Pratchett', 'Le Guin', 'Turner'}
Dictionary Comprehensions
A dictionary is a list that has a label at the start of it, we can use an existing dataset and
convert it into a dictionary using a dictionary comprehension.:
f-titles = {b.title: b for b in books if b.genre == 'fantasy'}
\_______/ \_/ \_____________/ \________________________/
Add label set for each book in list if genre attribute is “fantasy”
23
Object-Oriented Programming
Generator Experssions
If we were processing a large log file that had lots of lines in it, some of which had the
word "WARNING" in it. If the log file was very big (terabytes) and we were looking only
for lines with the word “WARNING” in them, we shouldn’t use a List Comprehension in
this case because they would temporarily create a list containing every line and then
search for the appropriate messages.
Instead if we use a generator, we avoid that issue because generators don’t create a
temporary list, they only write content out when they are instructed to, this is sometimes
called Lazy Evaluation, and it allows you to start using the list immediately:
import sys
InName = "InputFile.txt"
OutName = "OutputFile.txt"
If we wanted to remove the word “WARNING” out of each line, we could do:
W = (line.replace(' WARNING', ‘’) for line in file if 'WARNING' in line)
\_________________________/ \______________/ \_________________/
Replace ‘WARNING’ with blank for each line in the file if ‘WARNING’ is in line
If we wanted to do the same thing in a more object-oriented manner, we could use the
following code. Note that the yield command works exactly like the normal return
command (when you return a value from a method), but it temporarily returns control to
the calling method, and remembers where it was in a sequence in each new call.
def warnings_filter(insequence):
for line in insequence:
if 'WARNING' in line:
yield line.replace(' WARNING', '')
This will return the same result as the previous code snippet.
24
Object-Oriented Programming
Unit Testing
One of the most important classes in unittest is called TestCase which provides a
set of methods to compare values, set up tests and clean up after tests are finished. To
write unit tests, we create a subclass of TestCase and write methods to do the actual
testing. Typically we start all of these methods with the name test. Here’s an example:
import unittest
class CheckNumbers(unittest.TestCase):
def test_int_float(self):
self.assertEqual(1, 1.0)
# END test_int_float
# END CheckNumbers
If the assertion is found to be true, it returns “.”, and if it fails, it returns “F”.
Assetion Methods
Methods Description
assertEqual Accept two comparable objects and ensure the named
assertNotEqual equality holds.
assertTrue Accept a single expression, and fail if the expression
assertFalse does not pass an IF test.
assertGreater Accept two comparable objects and ensure the named
assertGreaterEqual inequality holds.
assertLess
assertLessEqual
asssertIn Ensure an element is (or is not) an element in a
assertNotIn container object.
assertIsNone Ensure an element is (or is not) the exact value None
assertIsNotNone (but not another false value).
assertSameElements Ensure two container objects have the same elements,
ignoring the order.
assertSequenceEqual Ensure two containers have the same elements in the
assertDictEqual same order. If there's a failure, show a code diff
assertSetEqual comparing the two lists to see where they differ. The
assertListEqual last four methods also test the type of the list.
assertTupleEqual
assertRaises Ensure a specific function call raises a specific exception.
To pass the assertFalse method the test should return False, None, 0, or an empty
list, dictionary, string, set, or tuple. To pass the assertTrue method the test should
return True, non-zero numbers, containers with values in.
25
Object-Oriented Programming
Unit Testing
def MyAverage(seq):
return sum(seq) / len(seq)
# END average
class TestAverage(unittest.TestCase):
def setUp(self):
self.stats = StatsList([1,2,2,3,3,4])
# END setUp
def test_mean(self):
self.assertEqual(self.stats.mean(), 2.5)
# END test_mean
def test_MyAverage(self):
self.assertRaises(ZeroDivisionError, MyAverage, [])
# END test_zero
# END CLASS TestAverage
The setUp is called individually before each test, so each test starts with a clean slate.
Built-in Exceptions
Some of the Python built-in exceptions are as follows:
Methods Description
AssertionError Raised when an assert statement fails.
AttributeError Raised when an attribute reference or assignment fails.
FloatingPointError Raised when a floating point operation fails.
IOError Raised when an I/O operation (such as a print
statement) fails for an I/O-related reason.
IndexError Raised when a sequence subscript is out of range.
MemoryError Raised when an operation runs out of memory but the
situation may still be rescued by deleting some objects.
OverflowError Raised when the result of an arithmetic operation is too
large to be represented.
RuntimeError Raised when an error is detected that doesn’t fall in any
of the other categories.
SyntaxError Raised when the parser encounters a syntax error.
ZeroDivisionError Raised when the second argument of a division or
modulo operation is zero.
Test cases should never have side effects.
26
Object-Oriented Programming
Development Models
Test-Driven Development
“Write tests first” is the key mantra of Test-Driven Development. The key concept is that
a developer shouldn’t write any code until they have written tests for that code first.
Test-Driven Development has two goals:
1. To ensure that tests are actually written, and written well. Too often developers
leave the design of tests until after the development process, and then don’t
bother because the code seems to work.
2. To help the developers envisage exactly what the code will do, and what
processes and modules it will interact with, thus testing becomes part of the
design process.
Test-driven development offers more than just validation of correctness, it can also drive
the design of a program. By focusing on the test cases first, we have to imagine how the
functionality is used by end-users (in the first case, the test cases). So, we are concerned
with the interface before the implementation.
27
Object-Oriented Programming
Development Models
FDD mandates code inspections is that research has shown time and again that when
done well, inspections find more defects and different kinds of defects than testing. Not
only that but by examining the code of the more experienced, knowledgeable developers
on the team and having them explain the idioms they use, less experienced developers
learn better coding techniques.
28
Object-Oriented Programming
29
Object-Oriented Programming
3. How are the following argument types used in the string Format method
o Unindexed arguments
o Indexed arguments
o Keyword arguments
13. Explain the goals of Test-Driven Development, and outline the TDD Cycle.
14. Explain the goals of Feature-Driven Development, and outline the FDD Cycle.
30
Object-Oriented Programming
Object-Oriented
Programming
In Java
Workbook
Damian Gordon
2020
Feel free to use any of the content in the guide with my permission.
31
Object-Oriented Programming
Table of Contents
1. Introduction to Java
3. Object-Oriented Java
32
Object-Oriented Programming
Introduction to Java
Java Introduction
Java was developed by James Gosling, Mike Sheridan, and Patrick Naughton, starting in
1991, with Java 1.0 released in 1996. There have been 15 version of Java up to 2020.
System.out.print("Hello World\n");
}
}
33
Object-Oriented Programming
Introduction to Java
Java Comments Java String Formatting
// A Single Line Comment length() Length of string
/* This is a multi-line toUpperCase() Make upper case
Comment */ toLowerCase() Make lower case
indexOf(Str) Find Str
Java Arithmetic Operators
+ Addition, 7 + 3 Java IF Statement
- Subtraction, 7 - 3 if (condition) {
* Multiplication, 7 * 3 // if condition is true
/ Integer Divsion, 7 / 3 } else {
// if condition is false
/ Real Divsion, 7.0 / 3.0 }
% Division Remainder, 7 % 3
Java SWITCH Statement
Java Variable Types switch(expression) {
int x; case x:
x = 15; // code block
int x = 15; break;
double x; case y:
x = 15.0; // code block
double x = 15.0; break;
char x; default:
x = ‘s’; // code block
char x = ‘s’; }
String x;
x = “Hello, World!”; Java WHILE Statement
String x = “Hello World!”; while (condition) {
boolean x; // code to be executed
x = false; }
boolean x = false;
Java FOR Statement
Java Conditional Operators for (initial; cond; inc) {
!= Is not equal to // code to be executed
== Is equal to }
> Is greater than
< Is less than Java Methods
>= Is greater than or equal to public class Main {
<= Is less than or equal to static void METHOD () {
// code to be executed
Java Logical Operators }
}
&& Logical AND
All methods are generally enclosed within a
|| Logical OR
class, and the method called main() is
! Logical NOT
executed first.
These can be used in conditions.
34
Object-Oriented Programming
Reading Methods
Method Description
nextBoolean() Reads a boolean value from the user.
nextByte() Reads a byte value from the user
nextDouble() Reads a double value from the user
nextFloat() Reads a float value from the user
nextInt() Reads a integer value from the user
nextLong() Reads a long value from the user
nextShort() Reads a short value from the user
File Handling
To control files we need to import the Scanner class, as well as the File class:
import java.io.File; // Import the File class
And then to read in a file, we do the following:
File myObj = new File("filename.txt");
Scanner myReader = new Scanner(myObj);
while (myReader.hasNextLine()) {
String data = myReader.nextLine();
System.out.println(data);
}
myReader.close();
File Methods
Method Description
getName() Returns the name of the file
getAbsolutePath() Returns the absolute pathname to the file
canWrite() Returns whether you can write to the file
canRead() Returns whether you can read from the file
length() Returns the length of the file
createNewFile() Creates a new file.
To write to a file, we import the FileWriter class, instead of thr the File class:
import java.io.FileWriter; // Import FileWriter class
And we can use the method write(String) to add to the file.
35
Object-Oriented Programming
There are also several methods to get, set, add and remove items from the linked list:
Method Description
get(index) Returns the item at location index.
set(index, value) Sets the item at location index to the value value.
remove(index) Removes the item at location index.
addFirst(value) Add an item to the start of the list with the value value.
addLast(value) Add an item to the end of the list with the value value.
removeFirst() Removes the first item from the list.
removeLast() Removes the last item from the list.
getFirst() Returns the first item of the list.
getLast() Returns the last item of the list.
clear() Clears the list.
Together this gives us a lot of functionality to manpulate linked lists.
36
Object-Oriented Programming
Object-Oriented Java
Basic Java Object-Oriented Programming
Declaring a class in Java is done as follows:
public class Main {
int x = 5;
}
And to declare an object, we do:
public class ExampleObj {
int x = 5;
Java Constructors
A constructor in Java is a special method that is used to initialize objects. The constructor
name must match the class name, and it cannot have a return type (like void). Also note
that the constructor is called when the object is created. All classes have constructors by
default: if you do not create a class constructor yourself, Java creates one for you.
public class ExampleObj {
int x;
public ExampleObj(int y) {
x = y;
}
37
Object-Oriented Programming
Object-Oriented Java
Java Interitance
Let’s look an example, the Car class (subclass) inherits the attributes and methods from
the Vehicle class (superclass):
class Vehicle {
protected String brand = "Ford"; // Vehicle attribute
public void honk() { // Vehicle method
System.out.println("Tuut, tuut!");
}
}
class Car extends Vehicle {
private String modelName = "Mustang"; // Car attrib
public static void main(String[] args) {
38
Object-Oriented Programming
4. When declaring the main method what is the meaning of “String []args”?
39
Object-Oriented Programming
10. How do you declare a Class in Java? How do you add attributes and methods?
40