Chapter 9 covers object oriented programming in Python. You will be working with classes, objects and inheritance.
To see an explanation of all lecture material in chapter 9, watch: https://youtu.be/V2fGg8bxDdw
To see sample exercises that go with the Try It Yourself sections in the chapter, download: chapter_09.zip
Python is an object oriented programming language.
Terminology used in Python includes:
Class - blueprint for creating objects where you define what data is stored and what actions can affect the data. A class is conceptual (it isn't anything you can manipulate with code until you instantiate it).
A class definition can be compared to a cake recipe. Where the recipe is the class and the cake is an instance of the class. Recipes require ingredients and instructions. Classes require variables and methods. You must use the ingredients and instructions to create the cake just like you must create a class object to store data in the variables and use the methods.
Instantiation - when you create an object using a class, you instantiate the object (you are creating something with the class blueprint).
Object - - one instance of the class. Once you create an object from a class, the object has an identity (a unique address), a state (the data that it stores), and behavior (the methods that it contains). As a program runs, an object’s state may change.
Attribute - data variable that is part of a class (other languages may refer to it as a member or data member)
Method - a function that is part of a class and must be invoked (or called) by a class object. Methods are used to create, modify or delete class objects. Some methods are built into the language and some are created by the developer.
Polymorphism - Python includes method overriding and it handles method overloading by using parameters with default values which makes them optional
Encapsulation - hides the details of the class from the outside world. You create class objects and call class methods, but you don't know the internals of how the class works. You don't know what attributes are created and you don't know how the different methods are coded.
Abstraction - achieved through encapsulation. It is the process of hiding the real implementation of an application from the user and emphasizing how to use the application
Inheritance - you pull in an existing class as a base so you have access to all its attributes and methods and then you add more attributes and methods to it.
Classes contain attributes and methods. Classes are typically created in external files and imported into your program.
To create a class, you need to use the keyword class followed by the name of the class you are creating and a colon.
Syntax: class ClassName:
Example: class Hobby:
By convention, class names are capitalized. If the class name consists of more than one word, you can use camel casing or you can use underscores _ between words.
Below the class name, you would include attributes and methods.
Coding and calling methods works similarly to coding and calling a function. The primary difference is methods require class objects and functions do not.
One method that is automatically called when you create an object is the constructor.
In Python, the constructor is named __init__() It has two underscores before init and two underscores after init. Constructors are used to set attributes to starting values (it initializes them).
In ALL methods, the first parameter is self.
NOTE: Python doesn't use get and set methods the same way other languages use them (other languages use them to encapsulate data). In Python, getters and setters are used to: 1) add validation logic required for getting or setting a value and 2) avoid direct access to a private variable
Syntax:
def __init__(self, attribute1, attribute2, attributeN):
self.attribute1 = attribute1
self.attribute2 = attribute2
self.attribute3 = attribute3
Example:
def __init__(self, name, description, specialty):
self.name = name
self.description = description
self.specialty = specialty
def printSpecialty(self):
print(f"You specialize in {self.specialty} {self.name}")
If you want to set a default value in the __init__ constructor, you simply omit the attribute in the parameter list and assign the default value
Example:
To create an object, you set the object variable equal to the name of the class and a set of parentheses. Inside the parentheses, you code the parameters for the constructor separated by commas.
Syntax: objectName = ClassName(argument1, argument2, argumentN)
or
objectName = ClassName(
parameter1=argument1,
parameter2=argument2,
parameter3=argument3,
parameter4=argument4
)
Example:
To access the attributes of an object, you code the name of the object followed by the dot operator (.) and the name of the attribute.
Example:
To call a method from an object, you code the name of the object followed by the dot operator (.), the name of the method, and a set of parentheses. Inside the parentheses, you code the parameters for the method separated by commas. The object itself will automatically go to the method as "self", so you don't need to include that in the parenthesis
Example:
Full Programming Example:
NOTE: We will be learning how to modularize classes, but for now we will include them at the top of the program.
You can delete class objects or attributes using the del keyword
Syntax: del objectName or del objectName.attribute
Example:
del hobby1
or
del hobby2.description
To see a video explanation, watch: https://youtu.be/HcIj41WT4CM
1. Open the CIT228 folder and create a new folder named Chapter9
2. Create a new file and call it restaurant_class.py (save the file into your Chapter9 folder)
3. Using the restaurant_class.py file, complete Try It Yourself 9-1 and then add the code for Try It Yourself 9-2 below the code for 9-1 (page 162)
Sample Output:
Exercise 9-1
=================================================================
-------------Here are your selections-------------
Restaurant= TGI Friday
Cuisine= American
TGI Friday serves American cuisine.
TGI Friday is open.
Exercise 9-2
=================================================================
Olive Garden serves Italian cuisine.
Hunan serves Chineese cuisine.
La Senorita serves Mexican cuisine.
4. Complete Try It Yourself 9-3 on page 162 and name the fiile user_class.py.
Sample Output:
Welcome back George!
George Jetson has a username of georgejetson,
a password of astro123 and an email address of george@jetson.net.
Welcome back Wilma!
Wilma Flintstone has a username of flinty,
a password of pebbles and an email address of wilma@flint.net.
Welcome back Betty!
Betty Rubble has a username of bets,
a password of bambam and an email address of bets@rub.com.
There are three ways to modify attribute values:
To modify the attribute using the object, use the objectName, a dot, and the attribute name in an assignment statement
Syntax: objectName.attribute = new value
hobby2.name="Weight Training"
hobby2.description="Free weights and machines"
hobby2.specialty="Arms and Legs"
You can call a method and pass values which will be assigned to the attribute within the method
Syntax: objectName.methodName(self, value)
New Class and Method Example: The newDestination method is assigning a new value to destination and totalMiles based on the data that was passed. It is also resetting milesTraveled and printing out a message.
Here's the section of code where the object invokes the newDestination method:
change=input("Do you want to enter a new destination? (y for yes)")
You can change values in methods using arithmetic expressions.
Example from the book: The odemeter reading is adjusted within a method
Here's the object invoking the method:
To see the full blown program, view: Car Example
Full Blown Trip Example: The milesTraveled method adds the miles passed by the user to the number of miles traveled. Because the user is entering input data in this program, numbers were automatically given the string data type. So, all numbers had to be converted to integer to perform arithmetic on them. In the __init__ constructor, data has been converted to int. You will also notice this in the newDestinaton method. For updateMiles, the data is converted to int within the program before the method is called (which is another way of converting the data)
To see a video explanation, watch https://youtu.be/SZmbIczCMLk
1. Open restaurant_class.py and save it as restaurant_attributes.py Complete Try It Yourself 9-4 on page 167 using the restaurant_attributes.py file. Feel free to modify the main program (you can remove the code from exercises 9-1 and 9-2. Make sure you have all the required number_served changes.
You are being asked to:
1) change the attribute to a different value in the main program
2) change the number_served attribute to a different value using the set_number_served method
3) add to the number_served using the increment_number_served method
Sample Output:
Exercise 9-4
=================================================================
Outback Steakhouse is open.
Outback Steakhouse serves American cuisine.
# processing initial number served #
The starting number of customers was: 4
# changing the number_served attribute to 200 #
The number of customers served has been changed to 200
# changing the number_served using the set_number_served method #
How many total customers have been served today?300
The number of customers served is currently 300
# addint to the number_served using the increment_number_served method #
How many additional customers have been served?45
# printing the grand total for the day #
The number of customers served this business day = 345
2. Complete Try it Yourself 9-5 on page 167 using the user_class.py file.
Partial output that includes new requirements from exercise 9-5
Flo Schmoe has a username of flow,
a password of eieiflo and an email address of flo@schmoe.net.
Flo has tried to login 1 times!
Flo has tried to login 2 times!
Flo has tried to login 3 times!
Flo has tried to login 4 times!
Flo has tried to login 5 times!
Flo you have exceeded the number of login attempts.
The number of attempts has been reset to: 0
Your account has been locked for 30 minutes, please try back later or call tech support for help!.
Inheritance lets you create a new class based on an existing class. You can use the methods and attributes of the existing class and just add the new attributes and methods that you want to use. If there is a method in the existing class that you don't like, you can override it and create your own.
The class you inherit from is called a base class or parent class (some languages also refer to it as a superclass).
The class you are creating is called the derived class or child class (some languages also refer to it as a subclass).
NOTE: Our book uses the terminology parent and child; however, you should be familiar with the different terms used for parent and child classes because many sites use them interchangably.
To create the child class, use the following syntax:
Syntax: class childClass(parentClass):
Example of a Student class derived from a Person parent class:
Our new child class cannot initialize parent class attributes with the __init__() constructor - the parent class must do that! We need to include a call to the parent class within the child class __init__() constructor and we need to pass the data the parent __init__() constructor needs.
There are 2 ways you can call the parent class, you can use the parent classname OR you can use the super() function which allows you to call any method from the parent class. The advantange of using the super() function is the child class will inherit all the methods and properties from its parent AND you will notice in the constructor, you do not have to pass "self" along to the parent if you use super()
Syntax:
def __init__(self, parentAttr1, parentAttr2, parentAttrN, childAttr1, childAttr2, childAttrN):
parentClass.__init__(self,parentAttr1, parentAttr2, parentAttrN)
self.childAttr1 = childAttr1
self.childAttr2 = childAttr2
self.childAttrN = childAttrN
or
def __init__(self, parentAttr1, parentAttr2, parentAttrN, childAttr1, childAttr2, childAttrN):
super().__init__(parentAttr1, parentAttr2, parentAttrN)
self.childAttr1 = childAttr1
self.childAttr2 = childAttr2
self.childAttrN = childAttrN
The new attributes of the child class are initialized in the child constructor after the parent class is called. They are initialized the same way you initialized values in the parent class.
Child class methods are also set up the same way as the parent class. If you include a method with the same name as the parent class, Python will look at the type of object invoking (or calling) the method. If it is a child class object, it will use the child class method. If it is a parent class object, it will use the parent class method.
Example using super() for the constructor. You should note the parent and child both have print classes. In the program, when the student1 object calls the print method, it will use the child print method because a child object is invoking it. When the person1 object calls the print method, it will use the parent class print method because of the object invoking it:
Everything you have learned up to this point applies to classes. The only difference is you need class objects to use attributes and methods within the class.
Because Python is loosely typed, you can include lists in classes or dictionaries. Python will determine the type of item being passed to the class and select the appropriate item type.
Example: In the code below, items that are entered by the user are appended to a list named tempItems. Once the user is done entering the items, the sales object is created and the list of items is passed to the class constructor along with the other information the user entered.
In a program where you use the same object instance to store different data, you can add the object to a list which allows you to access the data later in the program. This is no different than adding dictionary items to a storeList using the append method
In the code below, the sales object instance is added to storeList.append(sales).
Outside of the loop, you can still access the class objects using the list and you can use the object in the list to call class methods.
In the example below, s represents each class object stored in the list. You can use s to call any of the class methods.
Full example that includes list processing similar to your next assignment:
Specialty store is derived from Store. A list attribute named items has been added to Specialty. Specialty contains 2 methods: init constructor and displayItems which is set up to handle list processing. The main program allows the user to select how many stores they want to enter and to add input for all attributes. Each class object is created using the sales object name. After the information is displayed back to the user, the sales object is added to a list. Once the user is done entering information, the list of sales objects is processed displaying the store information and the item information.
If your class is becoming long and too detailed, you may need to pull out some attributes to create another class.
If you do that, you can still include the data as a class attribute by assigning it to the class you created.
Syntax: self.attribute = className()
If you do this, accessing attributes and methods can be a little tricky.
Example: To simplify the Trip class, I removed the mile information from the class and put it into a separate Miles class. Within the trip class, I added an object instance from Miles named mileInfo and I passed it totalMiles (this was all done in the __init__() constructor)
self.mileInfo = Miles(totalMiles)
So far, everything seems pretty straightforward. However, if you want to access attributes or methods in Miles, you must do it through the mileInfo attribute that was created.
To update the miles traveled you need to do something like this:
trip is the object created
mileInfo is the instance of the Miles class that is an attribute in the trip class
updateMilesTraveled is a method in the Miles class
To print miles left, you need to do something like this:
trip is the object created
mileInfo is the instance of the Miles class that is an attribute in the trip class
milesLeft is an attribute in the Miles class
Here's the fully revised program:
NOTE: The book has a similar example showing a car and battery class.
To see a video explanation, watch: https://youtu.be/TD15vCQMjis
1. Open restaurant_attributes.py and save it as restaurant_inheritance.py Complete Try It Yourself 9-6 on page 173 Feel free to remove code from the main program that pertains to exercise 9-4 (keep the Restaurant class intact). NOTE: The directions are asking you to add the flavors attribute as a list. The Store parent and Specialty child class example in the section above is similar to what you need to do.
2. Open user_class.py and name it user_inheritance.py. Complete Try It Yourself 9-7 and 9-8 on page 173 using the user_inheritance.py file Make any changes needed to the main program to accomplish the required tasks. You will have 3 classes: User, Admin derived from User and Privileges. Admin is connected to User because it is derived from user (it is a child of User) and it is connected to privileges because it includes a privilege object as an attribute
Here's how I set up Admin
To see an example similar to what you need to do, view: Magical Creatures
So far, we have created classes at the top of the programs that use them. In the real-world, classes are stored in separate files (modules) and they are imported into programs. This is very similar to what we did with functions.
We will cover how to create the class module and different ways to import the classes.
The class file should have a docstring at the top that states the purpose of the class. A docstring is a special comment the interpretter ignores. it begins with 3 double quotes and it ends with 3 double quotes. It can be on one line or multiple lines.
docstring Syntax: """ documentation text """
Example showing the Miles and Trip classes in their own file named TripMiles.py:
You can import a single class or multiple classes from a module. You can import them into a program OR into a module containing a class.
Syntax: from fileName import className1, className2, classNameN
This technique doesn't require any additional coding or prefixing of class methods. It is the technique used most often by developers.
Example importing the Trip and Miles class from the TripMiles module into a program
Example illustrating importing into a class module and importing parent and child class modules into a program:
store.py which contains the Store parent class
specialty.py which contains the Specialty child class and imports the Store parent class
myStore.py program which imports the Store class from the store module and the Specialty class from the specialty module
If you import the module and not the class with the module, when you create class objects, you will need to prefix the className with the moduleName (method class won't be impacted)
Syntax: import moduleName
Example: In the code below, the only thing that had to be modified was the statement creating the trip object. instead of trip = Trip(start,dest,miles), I had to use trip=TripMiles.Trip(start,dest,miles) Everything else remained the same
This may seem like the easy way out; however it is BAD practice because you don't know everything that may be in the module. Remember, these import techniques not only work for your own classes, but Python classes too. You could end up with naming conflicts and other issues if you do this.
This is not something we are going to do, but I wanted you to be aware of it in case you run into it online or at work.
Example:
from TripMiles import *
If you are importing a module (and not the class), and you have a very long module name, you can give it an alias that you can use in your code.
Syntax: import moduleName as alias
Partial Example: This is similar to importing the module, the only line of code impacted is the one involved in creating the object. The classname will need to be prefixed with the alias. You'll notice that trip = TrMi.Trip(start,dest,miles) instead of trip=Trip(start,dest,miles)
To see a video demonstration of part 2 and explanation of parts 1 and 3, watch: https://youtu.be/VMpfu7Ft9OI
1. Create 3 new files named: restaurant.py, icecream.py and myRestaurant.py
2. Open restaurant_inheritance.py.
a) Copy the Restaurant class and paste it into restaurant.py.
b) Copy the IceCreamStand class and paste it into icecream.py
c) Copy everything else below the two classes and paste the code into myRestaurant.py
3. Save all your changes and make the following adjustments:
a) At the top of icecream.py, add the following import statement to import the parent Restaurant class
from restaurant import Restaurant
b) At the top of the myRestaurant.py program, add the following import statements to bring in the Restaurant and Specialty classes
4. Save all your changes and run the myRestaurant.py program (everything should work without having to modify the code)
1. Create 4 new files named: user.py, admin.py, privileges.py and myUsers.py
2. Open user_inheritance.py
a) Copy the User class and paste it into user.py
b) Copy the Privileges class and paste it into privileges.py
c) Copy the Admin class and paste it into admin.py. Add 2 statements at the top to import the User class and the Privileges class (this is similar to what you did in icecream.py)
d) Copy all the code below the classes and paste it into myUsers.py. Add 3 statements at the top to import the User class, Privileges class and Admin class (this is similar to what you did in myRestaurant.py)
3. Save all your changes and run myUsers.py - you shouldn't have to make any adjustments to the code.
The chapter introduces 2 new functions in the random library: randint() and choice()
randint() randomly retrieves integers within the range you give it.
Example:
from random import randint
dice = randint(1,6)
print(dice)
choice() randomly retrieves an item from a list or tuple
Example:
from random import choice
1. Complete one of the following:
1. You should have the following files in your Chapter9 folder:
| Exercise | Assignment Files | Points |
|---|---|---|
| Hands On 1: Try It Yourself 9-1 and 9-2 | restaurant_class.py | 3 points |
| Hands On 1: Try It Yourself 9-3 | user_class.py | 3 points |
| Hands On 2: Try It Yourself 9-4 | restaurant_attribute.py | 3 points |
| Hands On 2: Try It Yourself 9-5 | user_class.py | 3 points |
| Hands On 3: Try It Yourself 9-6 | restaurant_inheritance.py | 5 points |
| Hands On 3: Try It Yourself 9-7 | user_inheritance.py | 6 points |
| Hands On #4 Part 1 | restaurant.py, icecream.py, myRestaurant.py | 3 points |
| Hands On #4 Part 2 | user.py, admin.py, privileges.py, myUser.py | 4 points |
| Hands On #4 Part 3 (Optional) | extra credit exercise | 10 points |
2. Upload Chapter9 to GitHub
a. Click the ... next to CIT228 Git and select the Changes menu, Stage all Changes command.
b. In the Message window below Source Control, enter Chapter9 and then click the ... next to CIT228 Git and select the Commit menu, Commit Staged command
c. Display the menu next to the CIT228 Git folder by selecting ... and select the Push command
d. This will put all files and folders inside your CIT228/Chapter9 directory into your GitHub repository
3. Open a web browser and go to your CIT228 repository. Make sure the Chapter9 directory and files are there, then copy the URL and paste it into the lab assignment dropbox (you are done with the second part of your lab assignment!)