Program design: course enrollment

Learn this with friends

ComputingIntro to computer science - Python6:026 check-ins

About this video

The narrator designs a Course class for school enrollment software, with title, instructor, capacity and a roster list, plus a __str__ method for printing. Testing reveals bugs, so the design adds an is_full method, calls it from inside enroll, and makes enroll and unenroll check the roster first to avoid overfilling, duplicates and a ValueError.

You'll be able to

  • design a class with an init method, attributes and methods from a description of a problem.
  • write a __str__ method so printing an object shows useful information.
  • call one method from inside another using self.
  • add validation inside a method so the object protects itself from bugs.

Key words

init method
The method that sets up an object's attributes when the object is created.
attribute
A piece of data stored on an object, such as a course's title or capacity.
string method (__str__)
A special method that tells Python how to show an object as a string when it is printed.
capacity
The maximum number of students a course can hold.
encapsulate
To keep logic, like validation checks, inside the class so users of the class don't have to remember it.
ValueError
The error Python raises here when you try to remove a name that isn't in the list.
Transcript

- [instructor[ Let's design a program with objects and methods. We're working on the enrollment software for a school that students use to sign up for courses. Each available course has a title, an instructor, a capacity, and a list of the students enrolled. The capacity tells us the maximum number of students the course can hold.

We want each course to keep track of its own information, so we'll want a course type. In terms of methods, a course supports two key actions. A student can enroll or unenroll. So let's write out our class definition. As always, we'll start with our init method, so we can set up the attributes for a course object.

The syntax always looks the same. We take our parameters and we store them on the object. Except our roster attribute, which we want to start out empty. So we set it to an empty list. Before we get too deep, let's test this. We go back to made.py, import the course module, and then create a course object.

But when I print my course, we get this not-so-useful representation. Instead, when I print a course, I want to actually show information about that course. So let's tell Python how to represent a course object as a string using the special string method. So Python can find it, we need to use the exact name, underscore, underscore, str, underscore, underscore.

And since it's a method, it needs to take the object as its first parameter. What should a course look like? Well, that's up to us as the programmer. Let's start by returning a string with the course's title and instructor. Inside the method, we need to make sure we're accessing the attribute defined on the object, so we access our object parameter self.attribute.

And now when I print the course, Python executes the string method. That's much better, but it would be useful to know how many students are enrolled out of how many total spots. So that's just the length of our roster with our capacity, which gives us this informative and nicely formatted string representation of a course.

Now onto our real course logic. In our original design, we said we needed two methods, enroll and unenroll. So let's add two new method definitions, which need to be indented inside of our class definition. Like all methods, our first parameter will be the object the method is acting on.

And then as the second parameter, we'll take the name of a student. Pretty straightforward. Enroll will just take that name and append it to our roster attribute. And then unenroll just removes the name from that list. To test our object, let's simulate an enrollment period.

We have a list of students in registrar.py. So let's iterate over that list and enroll each student in the journalism course. And then just to check that the opposite works, let's also unenroll all of the students. This tells us that we have 57 students enrolled out of a possible 22 spots.

So we're doing something wrong here. Our course object shouldn't let students enroll if the course is already full. This feels like a common question people might have about a course. So let's separate it out into its own method. If the course is full, the method should return true, or if there are still spots available, the method should return false.

To achieve this, we can just check if the current length of the roster is greater than or equal to the course capacity. Now, we could rely on the people who use our course class to always check if the course is full before they call enroll. But that feels like we're just asking for bugs.

So instead, let's encapsulate all of that validation logic inside the enroll method. If the course is full, we can't enroll the student, so we shouldn't update the roster attribute. But how do we call a method from inside another method? Well, normally, we call a method with the object name, dot, method name.

Inside a method, the object we're acting on is just the parameter itself. So we call self, which is our course object, dot, is full. And if it is full, we just do nothing and exit the method. If we run this again, good news, our enrollment is now capped at our capacity of 22.

But bad news, we now have a value error. This stack trace tells us that the error comes from our unenroll method call, specifically when we try to remove the name from the list. Hmm. Now that we've fixed enroll, the second half or so of the students aren't actually in the roster anymore.

So before we try to remove them, we should double-check that they're actually enrolled in the first place. And thinking more about this, we should probably check the opposite and enroll. We don't want a student to enroll in the same course twice, whether by accident or on purpose.

After one last test, our course enrollment system is ready for business. But since some courses tend to be in pretty high demand, our team is already onto the next project, planning a new wait list feature.

Video © Khan Academy, used under CC BY-NC-SA. Watch on Khan Academy. Puzzicle is not affiliated with Khan Academy.