0% found this document useful (0 votes)
47 views52 pages

ENGR 101 Introduction To Programming: Week 12

This document discusses dictionaries and classes in Python. It provides examples of using dictionaries as mappings between keys and values, and various dictionary methods like keys(), values(), and invert_dict(). It then introduces object-oriented programming concepts like classes, objects, and methods. Examples show creating a Point class with attributes like x and y, and a Time class with methods like print_time(), time_to_int(), and increment(). The document provides guidance on defining classes, initializing objects, and calling methods on instances.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
47 views52 pages

ENGR 101 Introduction To Programming: Week 12

This document discusses dictionaries and classes in Python. It provides examples of using dictionaries as mappings between keys and values, and various dictionary methods like keys(), values(), and invert_dict(). It then introduces object-oriented programming concepts like classes, objects, and methods. Examples show creating a Point class with attributes like x and y, and a Time class with methods like print_time(), time_to_int(), and increment(). The document provides guidance on defining classes, initializing objects, and calling methods on instances.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 52

ENGR 101

Introduction to
Programming
Week 12
Reminder
Last Week (Week 11)
Dictionaries
Dictionary – What is it?

• A dictionary is like a list, but more general.


 In a list, the indices have to be integers; in a dictionary
they can be (almost) any type.
• You can think of a dictionary as a mapping between a set
of indices (which are called keys) and a set of values.
• Each key maps to a value. The association of a key and a
value is called a key-value pair or sometimes an item.
Getting all keys or values

hist = {'a': 1, 'p': 1, 'r': 2, 't': 1}


print hist.keys()
[‘a’, ‘p’, ‘r’, ‘t’]
print hist.values()
[1, 1, 2, 1]

• Note: Keys have to be immutable!


Dictionary as a set of counters

# counters implementation
def histogram(s):
d = dict()
for c in s:
if c not in d:
d[c] = 1
else:
d[c] += 1
return d
The name of the function is histogram, which is a
statistical term for a set of counters (or frequencies).
Looping and dictionaries

#implementation
def print_hist(h):
for c in h:
print c, h[c]

h = histogram('parrot')
print_hist(h)
a 1
p 1
...
Reverse lookup

• Given a dictionary d and a key k, it is easy to find the


corresponding value v which is d[k]. This operation is
called a lookup.
• But, what if you have v and you want to find k?

# implementation
def reverse_lookup(d, v):
for k in d:
if d[k] == v:
return k
return -1
Dictionaries and lists

# inversion implementation
def invert_dict(d):
inv = dict()
for key in d:
val = d[key]
if val not in inv:
inv[val] = [key]
else:#keys appended as a list for same value
inv[val].append(key)
return inv
Dictionaries and lists

hist = histogram('parrot')
print hist
{'a': 1, 'p': 1, 'r': 2, 't': 1,
'o': 1}
inv = invert_dict(hist)
print inv
{1: ['a', 'p', 't', 'o'], 2: ['r']}
Week 12
Classes and Objects
A new programming paradigm

• So far, we have designed our programs around functions, i.e.


blocks of statements, which manipulate data.
 procedural programming
• An alternative way: combine data and functionality and wrap it
inside something called an object.
 object-oriented programming
• Why do we need this new way of programming?
 When writing large programs, it is a lot easier to develop
and maintain programs in object-oriented manner.
Object oriented programming

• Two main aspects of OOP:


 Classes and objects
• Class: creates a new type (blueprint for objects)
• Objects are instances of the class.
• All family cars [a class] have 4 wheels and an engine.
 My Corolla [an instance/object] is broken yesterday.
 There is a taxi [an instance/object] parked outside.
Object-oriented features

• Programs are made up of


 object definitions,
 function definitions
• Most of the computation is expressed in terms of
operations on objects.
• Object definition  an object/concept in real world
• Functions that operate on that object  the ways real-
world objects interact.
Classes

Contains two essential pieces:


• Attributes: properties of objects
 color of a car, engine type, wheel size, etc.

• Methods (i.e., functions on objects)


 start_engine(…)
 run_wipers(…)
 turn_on_headlights(…)
Classes: Syntax

class ClassName:
def __init__(self, …):
Attribute initializations

def method1_name(self, …):



def method2_name(self, …):

Classes: User-defined types

• Create a class called Point that represents a point in two-


dimensional space.
• Points are often written in parentheses with a comma
separating the coordinates.
 (0, 0) represents the origin
 (x, y) represents the point x units to the right and y
units up from the origin.
Classes: User-defined types

• Several ways to represent points in Python:


 Store the coordinates separately in two variables, x
and y.
 Store the coordinates as elements in a list or tuple.
 Create a new type, i.e., a class, to represent points as
objects.
Classes: A first example

class Point:
"""represents a point in 2-D space"""
def __init__(self, x, y):
self.x = x
self.y = y

• A class is like a factory for creating objects. To create a


Point object, you call Point as if it were a function.

blank = Point(0, 0)
Instances

• Creating a new object is called instantiation, and the


object is an instance of the class.
• When you print an instance, Python tells you what class it
belongs to and where it is stored in memory (the prefix 0x
means that the following number is in hexadecimal).
blank = Point(0, 0)
print blank
<__main__.Point instance at 0xb79d3ac>
Attributes

• Access attributes of an instance using dot notation:


print blank.x, blank.y
0 0
blank.x = 3.0
blank.y = 4.0
Instances & Attributes

print blank.x, blank.y


3.0 4.0
distance = math.sqrt(blank.x**2 + blank.y**2)
print distance
5.0

• You can also pass an instance as an argument:


def print_point(p):
print ‘(’ + str(p.x) + ‘,’ + str(p.y) + ‘)’
The init method

• The init method (short for “initialization”) is a special


method that gets invoked when an object is created.
• Its full name is __init__ (two underscore characters,
followed by init, and then two more underscores).
class Time:
def __init__(self, hour=0, minute=0, second=0):
self.hour = hour
self.minute = minute
self.second = second
Printing Time objects

def print_time(t):
print str(t.hour) + ‘:’ + \
str(t.minute) + ‘:’ + \
str(t.second)
The init method

• The parameters are optional, so if you call Time with no


arguments, you get the default values.
time = Time()
print_time(time)
0:0:0
• If you provide one argument, it overrides hour:
time = Time(9)
print_time(time)
9:0:0
The init method

• If you provide two arguments, they override hour and


minute.
time = Time(9, 45)
print_time(time)
9:45:0

• And if you provide three arguments, they override all


three default values.
Methods
Methods

• Methods are semantically the same as functions, but


there are three syntactic differences:
 Defined inside a class definition
 The syntax for invoking a method is different from the
syntax for calling a function.
 The first parameter of a method is always ‘self’ (self
is not a reserved word, but commonly used as a
convention).
Methods – Printing time

• Define a method called print_time:


# implementation
class Time:
def print_time(self):
print str(self.hour) + ‘:’ + \
str(self.minute) + ‘:’ + \
str(self.second)

• Self refers to the current object that the method is called


on, or being created.
Methods – Printing time
class Time:
def print_time(self):
print str(self.hour) + ‘:’ + \
str(self.minute) + ‘:’ + \
str(self.second)

start = Time(9, 45)


Time.print_time(start) # method call via class name
09:45:0
start.print_time() # method call via a class instance
09:45:0
In-Class Exercise

• Implement time_to_int() method.

# inside class Time


def time_to_int(self):
minutes = self.hour * 60 + self.minute
seconds = minutes * 60 + self.second
return seconds
In-Class Exercise

• Implement int_to_time() method.

# inside class Time


def int_to_time(self, seconds):
hour = (seconds/3600) % 24
minute = (seconds / 60)%60
second = seconds % 60
return Time(hour, minute, second)
Methods – Another exercise

# inside class Time


def increment(self, seconds):
tot_secs = seconds + self.time_to_int()
return self.int_to_time(tot_secs)
Methods

Start = Time(9, 45)


start.print_time()
09:45:0
end = start.increment(1337)
end.print_time()
10:7:17

• Sometimes it may be confusing due to self param.


end = start.increment(1337, 460)
TypeError: increment() takes exactly 2
arguments (3 given)
Methods

• is_after takes two Time objects as parameters.


# inside class Time:
def is_after(self, other):
return self.time_to_int() >
other.time_to_int()

• To use this method, you have to invoke it on one object


and pass the other as an argument:
class Time:
def __init__(self, hour=0, min=0, sec=0):
self.hour = hour
self.minute = min
self.second = sec

def print_time(self):
print str(self.hour) + ':' + str(self.minute) + \
':' + str(self.second)

def time_to_int(self):
total_seconds = self.hour * 3600
total_seconds += self.minute * 60
total_seconds += self.second
return total_seconds

def int_to_time(self, tot_secs):


hour = (tot_secs / 3600) % 24
minute = (tot_secs % 3600) / 60
second = tot_secs % 60

t = Time(hour, minute, second)


return t

def increment(self, x):


total_secs = self.time_to_int() + x
return self.int_to_time(total_secs)
time1 = Time(10, 30)
time1.print_time()
print time1.time_to_int()
time2 = time1.int_to_time(3700)
time1.print_time()
time2.print_time()
time3 = time2.increment(20)
time3.print_time()
time2.print_time()

Output:
10:30:0
37800
10:30:0
1:1:40
1:2:0
1:1:40
import math
class Point:
def __init__(self, x ,y):
self.x = x
self.y = y

def get_dist_from_origin(self):
return math.sqrt(self.x**2 + self.y**2)

def get_dist_from_another_point(self, p):


return math.sqrt((self.x - p.x)**2 + (self.y - p.y)**2)

point1 = Point(3, 5)
point2 = Point(0, 0)

print point1.get_dist_from_origin()
print point1.get_dist_from_another_point(point2)

Output:
5.83095189485
5.83095189485
Rectangles

• For example, imagine you are designing a class to


represent rectangles.

What attributes would you use to specify the location


and size of a rectangle?
Rectangles

• There are at least two possibilities:


 You could specify one corner of the rectangle, the
width, and the height.
 You could specify two opposing corners.
Rectangles

class Rectangle:
"""represent a rectangle.
attributes: width, height, corner.
"""
def __init__(self, width, height, x, y):
self.width = width
self.height = height
self.corner = Point(x, y)
Rectangles

• Instantiate a Rectangle object and assign values to the


attributes:
box = Rectangle(100, 200, 0, 0)
Rectangles
Objects are mutable

• You can change the state of an object by making an


assignment to one of its attributes.
 For example, to change the size of a rectangle
without changing its position, you can modify the
values of width and height:
box.width = box.width + 50
box.height = box.height + 100
Instances as return values

Functions can return instances. For example, find_center


takes a Rectangle as an argument and returns a Point that
contains the coordinates of the center of the Rectangle:

# implementation
def find_center(box):
p = Point()
p.x = box.corner.x + box.width/2.0
p.y = box.corner.y + box.height/2.0
return p
Copying

• Aliasing can make a program difficult to read


 changes in one place might have unexpected effects
in another place.
 hard to keep track of all the variables that might
refer to a given object.
• Copying an object is often an alternative to aliasing.
 “copy” module
Copying

p1 = Point()
p1.x = 3.0
p1.y = 4.0
import copy
p2 = copy.copy(p1)
• p1 and p2 contain the same data, but they are not the
same Point.
Copying

• If you use copy.copy to duplicate a Rectangle, note that it copies


the Rectangle object but not the embedded Point.

box = Rectangle(100, 200, 0, 0)


box2 = copy.copy(box)
print box2 is box
False
print box2.corner is box.corner
True
Copying

• This operation (copy.copy) is called a shallow copy because it


copies the object, but not the embedded objects.
• The copy module contains a method named deepcopy that copies
not only the object but also the objects it refers to, and the objects
they refer to, and so on. This operation is called a deep copy.

box3 = copy.deepcopy(box)
print box3 is box
False
print box3.corner is box.corner
False
Debugging
• If you try to access an attribute that doesn’t exist:
p = Point(0, 0)
print p.z
AttributeError: Point instance has no
attribute 'z'
• To check whether an object has a particular attribute:
print hasattr(p, ‘z')
False
• If you are not sure what type an object is, you can ask:
print type(p)
<type '__main__.Point’>
Exercises
Exercise 1

• Define a class Employee that will have as


attributes name and salary.

• Whenever you create


a new employee instance it should print
out “You added a new employee, their name
is: <given name>”.

• Add a method to change to be able to


update the salary.
Exercise 2
• Define a class Student that has two attributes: name
and a dictionary of courses by semester
(e.g. {‘Semester4’:{‘PHYS101’:3, ‘CS 100’:1}}

Note: the values for course codes are credits.

• Add a method that takes an argument like ‘SemesterX’ as


input (X can be 1-8) and
prints all the courses student took in that semester
along with total number of credits that semester.

>> student1 = Student("Alper", {"Semester1":{"PHYS


101":3, "MATH 101":3}})
>> student1.semester_history("Semester1")
PHYS 101
MATH101
Total credits in Semester1: 6

You might also like