COMPSCI 107 Computer Science Fundamentals

Slides:



Advertisements
Similar presentations
Python Objects and Classes
Advertisements

Lecture 04 – Classes.  Python has a number of classes built-in  lists, dictionaries, sets, int, float, boolean, strings  We can define our own classes.
Abstract Data Type Fraction Example
Classes 2 COMPSCI 105 SS 2015 Principles of Computer Science.
1 CS2200 Software Development Lecture 27: More Testing A. O’Riordan, 2008 K. Brown,
Abstract Data Type (ADT). 2 An Abstract Data Type (ADT) is a data structure with a set of operations –Operations specify how the ADT behaves, but does.
Lecture 05 – Classes.  A class provides the definition for the type of an object  Classes can store information in variables  Classes can provide methods.
Classes 2 COMPSCI 105 S Principles of Computer Science.
Guide to Programming with Python
Chapter 6—Objects and Classes The Art and Science of An Introduction to Computer Science ERIC S. ROBERTS Java Objects and Classes C H A P T E R 6 To beautify.
Classes 3 COMPSCI 105 S Principles of Computer Science.
Inheritance. Inhertance Inheritance is used to indicate that one class will get most or all of its features from a parent class. class Dog(Pet): Make.
Chapter 11 Introduction to Classes Intro to Computer Science CS1510, Section 2 Dr. Sarah Diesburg.
Prof. Amr Goneid, AUC1 CSCE 210 Data Structures and Algorithms Prof. Amr Goneid AUC Part R1. ADTs as Classes.
Programming in Java Unit 2. Class and variable declaration A class is best thought of as a template from which objects are created. You can create many.
Case Study - Fractions Timothy Budd Oregon State University.
Chapter 12 More on Classes. "The Practice of Computing Using Python", Punch & Enbody, Copyright © 2013 Pearson Education, Inc. The three OOP factors Remember,
JAVA Classes Review. Definitions Class – a description of the attributes and behavior of a set of computational objects Constructor – a method that is.
Topic 1 Object Oriented Programming. 1-2 Objectives To review the concepts and terminology of object-oriented programming To discuss some features of.
Chapter 10 Defining Classes. The Internal Structure of Classes and Objects Object – collection of data and operations, in which the data can be accessed.
Overview The Basics – Python classes and objects Procedural vs OO Programming Entity modelling Operations / methods Program flow OOP Concepts and user-defined.
1 Programming for Engineers in Python Autumn Lecture 6: More Object Oriented Programming.
Computer Science 111 Fundamentals of Computer Programming I Working with our own classes.
Object-Oriented Programming © 2013 Goodrich, Tamassia, Goldwasser1Object-Oriented Programming.
Classes COMPSCI 105 SS 2015 Principles of Computer Science.
Lecture 09 – Classes.  At the end of this lecture, students should be able to:  Define a new class  Store state information about instances of the.
More about Java Classes Writing your own Java Classes More about constructors and creating objects.
Topic 8Classes, Objects and Methods 1 Topic 8 l Class and Method Definitions l Information Hiding and Encapsulation l Objects and Reference Classes, Objects,
Class Example - Rationals Rational numbers are represented by the ratio of two integers, a numerator and a denominator, e.g., 2/3. This is opposed to irrational.
Topic 1 Object Oriented Programming. 1-2 Objectives To review the concepts and terminology of object-oriented programming To discuss some features of.
XuanTung Hoang 1 Something to discuss Feedbacks on Midterm Exam Final exam and term project  Final exam requires solid knowledge/skills in Java  Be more.
Geoff Holmes and Bernhard Pfahringer COMP206-08S General Programming 2.
CSC 108H: Introduction to Computer Programming Summer 2011 Marek Janicki.
CMSC201 Computer Science I for Majors Lecture 25 – Classes
COMPSCI 107 Computer Science Fundamentals
Topics Designing a Program Input, Processing, and Output
Object Oriented Programming
Classes and Objects – digging deeper
Mathematical operators overload
Topic 7 Introduction to Classes and Objects
Software Development Java Classes and Methods
Java Programming: Guided Learning with Early Objects
CS-104 Final Exam Review Victor Norman.
Fundamentals of Programming II Interfaces and Implementations
Chapter 3: Using Methods, Classes, and Objects
Variables, Expressions, and IO
Fundamentals of Programming I More Data Modeling
The CS 5 Times-Picayune Claremont Penguin Takes Olympics Gold
Creating and Deleting Instances Access to Attributes and Methods
Object Oriented Programming in Python Session -3
Classes In C#.
Subroutines Idea: useful code can be saved and re-used, with different data values Example: Our function to find the largest element of an array might.
Object-Oriented Programming
Fraction Abstract Data Type
Teach A-Level Computer Science: Object-Oriented Programming in Python
Java Classes and Objects 3rd Lecture
Object Oriented Programming in Python
More on Classes and Objects
Fundamentals of Programming I More Data Modeling
Topics Designing a Program Input, Processing, and Output
Topics Designing a Program Input, Processing, and Output
CIS 199 Final Review.
Designing a class.
Class Example - Rationals
Lecture 18 Python OOP.
A Level Computer Science Topic 6: Introducing OOP
Class rational part2.
More Basics of Python Common types of data we will work with
Classes and Objects Systems Programming.
Presentation transcript:

COMPSCI 107 Computer Science Fundamentals Lecture 09 – Classes

Learning outcomes At the end of this lecture, students should be able to: Define a class that overrides the default behaviour for standard operations COMPSCI 107 - Computer Science Fundamentals

Example: a Fraction class Consider writing a class to represent a fraction in Python Create a fraction Add, subtract, multiply, divide two fractions Display a text representation of a fraction numerator 1 / 2 denominator

Example: a Fraction class class Fraction: pass f = Fraction() f.num = 1 f.den = 2 print('{} / {}'.format(f.num, f.den))

Example: a Fraction class Placing the definition of the Fraction class in a separate file helps to “abstract away” the details of the class implementation from the client code Fraction.py main.py class Fraction: pass from Fraction import Fraction f = Fraction()

Example Fraction object (aka “instance” of the Fraction class) f

Example 1 num den 2 f Fraction object (aka “instance” of the Fraction class) num 1 den 2 f

Visualising Fraction objects We could create several Fraction objects as follows: f1 = Fraction(1, 2) f2 = Fraction(3, 4) f3 = Fraction(7, 8) 1 numerator 2 denominator f1 3 numerator f2 4 denominator f3 7 numerator 8 denominator

Initialiser for the Fraction class All classes must have an initialiser The initialiser for the Fraction class should store the numerator and the denominator Fraction.py class Fraction: def __init__(self, top, bottom): self.numerator = top self.denominator = bottom

Using the Fraction class So far we can create a Fraction object: We can access the state variables directly Although it is considered not good practice to do so What else can we do with Fraction objects? Nothing yet... we need to write the methods! main.py from Fraction import Fraction f1 = Fraction(3, 4) main.py print(f1.numerator) print(f1.denominator)

Using the Fraction class Why is accessing the state variables directly not advised? from Fraction import Fraction f1 = Fraction(3, 4) print(f1.numerator) print(f1.denominator) f1.denominator = 0 This shouldn’t be allowed – but currently we can’t prevent people using our Fraction class like this. What can we do?

Hiding the instance variables To prevent direct modification of the data fields (instance variables), we can stop the client (the user of the class) from accessing them directly This is known as data hiding, which can be done by defining private data fields in a class In Python, the private data fields are defined with two leading underscore characters You can also define private methods in the same way (although this is not something we will do) class Fraction: def __init__(self, top, bottom): self.__numerator = top self.__denominator = bottom

Accessing private data fields Private data fields can be accessed by code within the class definition, but they cannot be accessed by code outside the class (client code) To make a private data field accessible to the client, provide a method to return its value To enable a private data field to be modifiable, provide a method to set its value f1 = Fraction(3, 4) print(f1.__numerator) Traceback (most recent call last): File "lecture.py", line 5, in <module> print(f1.__numerator) AttributeError: 'Fraction' object has no attribute '__numerator'

Accessor and mutator methods A “get” method is referred to as an accessor method A “set” method is referred to as a mutator method def get_numerator(self): return self.__numerator def set_numerator(self, top): self.__numerator = top Example: accessing the private data fields through accessor and mutator methods from Fraction import Fraction f1 = Fraction(1, 2) print(f1.get_numerator()) f1.set_numerator(12) 1 12

Overriding default behaviour All classes get a number of special methods provided by default including methods for creating a text-based representation of the object and methods for comparing two objects of the class type But these default versions are not very useful. We should define our own that make more sense for our class. f1 = Fraction(1, 2) f2 = Fraction(1, 2) print(f1) print(f1 == f2) Calls a special function “__str__” <Fraction.Fraction object at 0x025E7410> False Calls a special function “__eq__”

The __str__ method You should define a __str__ method in your class This should return a “nicely-formatted” version of the object class Fraction: def __init__(self, top, bottom): self.__numerator = top self.__denominator = bottom .... def __str__(self): return '(' + str(self.__numerator) + '/' + str(self.__denominator) + ')' f1 = Fraction(1, 2) print(f1) (1/2)

The __eq__ method The __eq__ method will be called automatically whenever you use “==” to compare two instances of your class the default behaviour just compares the references class Fraction: def __init__(self, top, bottom): self.__numerator = top self.__denominator = bottom def __eq__(self, other): return self.__numerator * other.__denominator == other.__numerator * self.__denominator f1 = Fraction(1, 2) f2 = Fraction(3, 4) f3 = Fraction(3, 6) print(f1 == f2) print(f1 == f3) False True

The __repr__ method There is one more special method that you should define The __repr__ method should return “a string that unambiguously describes the object” Ideally, the representation should be an expression that could be used to create the object class Fraction: def __init__(self, top, bottom): self.__numerator = top self.__denominator = bottom .... def __repr__(self): return 'Fraction(' + str(self.__numerator) + ', ' + str(self.__denominator) + ')' If you don’t define __str__ then by default it will call __repr__, but otherwise __str__ is used for printing. In this example, we call __repr__ explicitly using repr() f1 = Fraction(1, 2) print(repr(f1)) Fraction(1, 2)

Overloading operators Python operators work for built-in classes But the same operator behaves differently with different types For example, consider “+” Performs arithmetic between two numbers Merges two lists Concatenates two strings Operator overloading is when one operator can perform different functions depending on the context

The __add__ method Another special method is __add__ (5/6) This is called automatically when the “+” operator is used In other words, f1 + f2 gets translated into f1.__add__(f2) class Fraction: def __init__(self, top, bottom): self.__numerator = top self.__denominator = bottom def __add__(self, other): new_num = self.__numerator * other.__denominator + self.__denominator * other.__numerator new_den = self.__denominator * other.__denominator return Fraction(new_num, new_den) f1 = Fraction(1, 2) f2 = Fraction(1, 3) result = f1 + f2 print(result) (5/6)

Improving the __eq__ method Recall the __eq__ method in our Fraction class: What happens here? def __eq__(self, other): return self.__numerator * other.__denominator == other.__numerator * self.__denominator x = Fraction(2, 3) y = Fraction(1, 3) z = y + y print(x == z) print(x is z) w = x + y print(w == 1)

Improving the __eq__ method Recall the __eq__ method in our Fraction class: What happens here? def __eq__(self, other): return self.__numerator * other.__denominator == other.__numerator * self.__denominator x = Fraction(2, 3) y = Fraction(1, 3) z = y + y print(x == z) print(x is z) w = x + y print(w == 1)

Improving the __eq__ method Recall the __eq__ method in our Fraction class: What happens here? def __eq__(self, other): return self.__numerator * other.__denominator == other.__numerator * self.__denominator x = Fraction(2, 3) y = Fraction(1, 3) z = y + y print(x == z) print(x is z) w = x + y print(w == 1) True False Traceback (most recent call last): File "lecture.py", line 13, in <module> print(w == 1) File "Fraction.py", line 19, in __eq__ return self.__numerator * ... AttributeError: 'int' object has no attribute '_Fraction__denominator'

Improving the __eq__ method To fix this, we need to check if the type of “other” is a Fraction object But maybe we would like to be able to compare Fraction objects to integers? we could extend this so that if the type of “other” is an int, then we perform an appropriate comparison. def __eq__(self, other): if not isinstance(other, Fraction): return False return self.__numerator * other.__denominator == other.__numerator * self.__denominator

Simplifying fractions There is no need to store numerators or denominators larger than required Simplifying fractions: calculate the greatest common divisor(GCD) of the numerator and denominator (i.e. the common divisors of 12 and 30 are 1, 2, 3 and 6) divide both numerator and denominator by GCD 12 / 30 is the same as 2 / 5

Calculating the GCD Fortunately, Euclid came up with a nice algorithm for computing this around 300BC Given two number, n and m, find the number k such that k is the largest number the evenly divides both n and m: Notice also that there is no “self” as the first input to this method. We will not be calling this method on an object – this is an example of a static method (it is not called on an object of the class) class Fraction: .... def __gcd(m, n): while m % n != 0: old_m = m old_n = n m = old_n n = old_m % old_n return n By defining this method with a leading “__”, it makes it private to the Fraction class. Client code (that uses the Fraction class) cannot directly call the gcd method (it is only used by the Fraction class itself to reduce fractions)

Improving the constructor Now we can improve the constructor so that it always represents a fraction using the “lowest terms” (reduced) form: class Fraction: def __init__(self, top, bottom): common = Fraction.__gcd(top, bottom) self.__numerator = top // common self.__denominator = bottom // common Notice how static methods are called using the name of the class (and not a particular instance of the class)

Improving the constructor Example from Fraction import Fraction x = Fraction(2,3) y = Fraction(3,4) z = x + y print(z) w = z + Fraction(5, 12) print(w) print(w + Fraction(1,6) == Fraction(2,1)) (17/12) (11/6) True

Other standard Python operators Many standard operators and funtions: https://docs.python.org/3/library/operator.html Common Arithmetic operators object.__add__(self, other) object.__sub__(self, other) object.__mul__(self, other) object.__floordiv__(self, other) object.__truediv__(self, other) Common Relational operators object.__lt__(self, other) object.__le__(self, other) object.__eq__(self, other) object.__ne__(self, other) object.__gt__(self, other) object.__ge__(self, other)

Summary A class is a template, a blueprint and a data type for objects A class defines the data fields of objects, and provides an initialiser for initialising objects and other methods for manipulating data The initialiser is always called __init__() The first input parameter is always “self”, and this refers to the object being constructed The data fields in the class should be hidden to prevent data tampering and to make the class easy to maintain This is achieved by prefixing the field name with __ We can override the default methods in a class definition Such as __repr__ and __str__ and __eq__