Objects and Classes

CS 65: Introduction to Computer Science I

Objects

An object is something that has data and methods (i.e., functions) associated with it.

Almost everything in Python can be considered an object - anything you can use the dot notation with to call a method is an object.

In [ ]:
#lists are objects
rainfall_amounts = [0.0, 0.3, 0.71, 0.0, 0.32, 1.1, 0.4]
rainfall_amounts.index(0.3) #index() is a list method
rainfall_amounts.sort() #sort() is a list method
In [ ]:
#strings are objects
my_string = "Hello"
my_string.lower()

with open("top_female_baby_names_2010s.txt") as namesfile:
    name_list = namesfile.readlines()  #readlines() is a method you can use with files
    

Some imported modules provide objects

In [1]:
import translate

#Translator is an object
translator = translate.Translator(to_lang="Spanish")

english_text = input("Enter some English text: ")
spanish_text = translator.translate(english_text) #tanslate() is a method
print("Spanish text:",spanish_text)
Enter some English text: I love computer science.
Spanish text: Amo las ciencias de la computación.

Example: Date object

Let's look at the date type, which is a type available in the datetime module.

In [12]:
import datetime

decl_ind_date = datetime.date(1776,7,4)

#datetime.date is a type
print( type(decl_ind_date) )

#weekday method returns the number of the day of the week this date fell on (0 = Monday, 6 = Sunday)
print( decl_ind_date.weekday() ) 
<class 'datetime.date'>
3

In addition to having methods, objects also have attributes, which are data values associated with the object.

Attributes can be accessed with the dot notation too, but there's no parentheses:

In [13]:
print( decl_ind_date.month )
print( decl_ind_date.day )
print( decl_ind_date.year )
7
4
1776

Group Exercise:

Write a program that will ask the user for their birthday and then display what day of the week that was on. Here's a start...

In [ ]:
day_names = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]
bday_year = int(input("Enter your birth year: "))
bday_month = int(input("Enter your birth month (1-12): "))
bday_day = int(input("Enter the day of the month you were born (1-31): "))

#finish the rest of the program here

Another example: Image objects also have attributes and methods

In [18]:
from PIL import Image

with Image.open("griff.jpg") as griff_image:
    
    print( type(griff_image) )
    
    print(griff_image.size) #size is an attribute of the griff_image object

    pixels = griff_image.load() #load() is a method
<class 'PIL.JpegImagePlugin.JpegImageFile'>
(732, 412)

Creating your own types

You can create your own type in Python using classes

Classes allow you to encapsulate data and actions-on-that-data together into one thing - this is an abstraction technique - it's good programming.

A class defines how objects behave - it is a blueprint that can be used to create many different objects of that type

Syntax:

  • keyword class
  • a name you decide (by convention, start with uppercase letter)
  • a colon :
  • indented list of function definitions (i.e., method definitions)
    • each method has a parameter called self which refers to the particular object being used at that time
In [22]:
class Motivator:
    
    def message1(self):
        print("You can do it!")
        
    def message2(self):
        print("I'm proud of you!")
        
m = Motivator()

print( type(m) )

m.message1()
<class '__main__.Motivator'>
You can do it!

Objects can also have attributes

Any attribute can be accessed in any of the class's methods using self. Each object of the class has a different set of all the attributes (just like different date objects represent different dates on the calendar)

In [23]:
class Motivator:
    
    def message1(self):
        print("You can do it,",self.name)
        
    def message2(self):
        print("I'm proud of you,",self.name)
        
eric_motivator = Motivator()
eric_motivator.name = "Eric"
eric_motivator.message1()

tim_motivator = Motivator()
tim_motivator.name = "Tim"
tim_motivator.message1()
You can do it, Eric
You can do it, Tim

Rectangle class example

In [24]:
class Rectangle:
    """
    Used for representing rectangles
    
    attributes: length, width
    """
    def area(self):
        return self.length*self.width
    
    def perimeter(self):
        return 2*self.length + 2*self.width
    
rec1 = Rectangle() #instantiates a new object of type Rectangle
rec1.length = 5
rec1.width = 10
print("Rectangle 1's area:", rec1.area() ) # self is rec1 here
print("Rectangle 1's perimeter:", rec1.perimeter() )


rec2 = Rectangle() #instantiates a new object of type Rectangle
rec2.length = 2
rec2.width = 3
print("Rectangle 2's area:", rec2.area() ) # self is rec2 here
print("Rectangle 2's perimeter:", rec2.perimeter() )
Rectangle 1's area: 50
Rectangle 1's perimeter: 30
Rectangle 2's area: 6
Rectangle 2's perimeter: 10

Notice:

I have multiple rectangle objects but only one class definition

A class is a blueprint for creating many objects - it's like how you can build many houses in a neighborhood from one set of blueprints.

Object-oriented programming: a popular style of programming that centers on creating custom classes and objects instantiated from those classes.

What if you don't define the attributes for your object?

What happens if we never define the attributes like rec1.length or rec1.width?

Exercise: Try this code and discuss what happens in your group.

In [ ]:
class Rectangle:
    """
    Used for representing rectangles
    
    attributes: length, width
    """
    def area(self):
        return self.length*self.width
    
    def perimeter(self):
        return 2*self.length + 2*self.width

rec3 = Rectangle()
print( rec3.area() )

Takeaway: you should never let this happen - we'll now see how to prevent it.

Initializer Method

The initializer method is a method with a special name: __init__() that gets called automatically when a new object for that class is created.

Note: that's two underscores before and two underscores after init.

In [25]:
class Rectangle:
    """
    Used for representing rectangles
    
    attributes: length, width
    """
    def __init__(self):
        self.length = 0
        self.width = 0
        
    def area(self):
        return self.length*self.width
    
    def perimeter(self):
        return 2*self.length + 2*self.width
    
rec4 = Rectangle() #this causes the __init__() method to run
print( rec4.area() )
0
In [26]:
rec4.length = 5
rec4.width = 20
print( rec4.area() )
100
In [27]:
print( rec4.perimeter() )
50

Passing arguments to the initializer method

You can set up any method with more parameters than just self.

Now this works a lot more like the date class we used earlier.

In [28]:
class Rectangle:
    """
    Used for representing rectangles
    
    attributes: length, width
    """
    def __init__(self, starting_length, starting_width):
        self.length = starting_length
        self.width = starting_width
        
    def area(self):
        return self.length*self.width
    
    def perimeter(self):
        return 2*self.length + 2*self.width
    
#7 gets passed to starting_length
#5 gets passed to starting_width
rec5 = Rectangle(7,5) 
print( rec5.area() )
35

Group Exercises

Using this version of the Rectangle class, do the following.

Exercise 1: Ask the user to give you the dimensions of two rectangles, and create Rectangle objects for each one. Then, tell the user which rectangle has a larger area.

Exercise 2: Add a new attribute to the Rectangle class called color. Create a new method that does something with this attribute.

Exercise 3: Create a Cuboid class for representing three-dimensional objects with a length, width, and height. Examples of real-world cuboids are things like six-sided dice, bricks, etc. Come up with at least two methods that would be useful for a Cuboid to have.