Abstract Classes in Python
Sarah Schlueter
Posted on December 20, 2023
Hey everyone! I've been working on HackerRank's coding challenges and decided to start documenting what I learn so that I can learn it on a deeper level and also maybe help anyone else out there also learning.
Today I am working on HackerRank's 30 Days of Code Challenges - Day 13: Abstract Classes.(https://www.hackerrank.com/challenges/30-abstract-classes)
I've been working a lot in C# for school lately, but I was previously learning Python over the summer, so I will do this challenge in Python3 as a refresher.
The task is as follows:
Given a Book
class, write a MyBook
class that does the following:
- Inherits from
Book
- Has a parameterized constructor taking these 3 parameters:
- string title
- string author
- int price
- Implements the Book class' abstract display() method so it prints these 3 lines:
-
Title:
, a space, and then the current instance's title. -
Author:
, a space, and then the current instance's author. -
Price:
, a space, and then the current instance's price.
-
The following starter code is provided:
from abc import ABCMeta, abstractmethod
class Book(object, metaclass=ABCMeta):
def __init__(self,title,author):
self.title=title
self.author=author
@abstractmethod
def display(): pass
#Write MyBook class
title=input()
author=input()
price=int(input())
new_novel=MyBook(title,author,price)
new_novel.display()
The first thing I do is check out the starter code to get a feel for what it's doing. We can see the first line of code imports tools from Python's abc
module to create abstract base classes. Abstract base classes serve as blueprints for other classes, enforcing the implementation of specific methods in all subclasses that inherit from them.
The next line defines Book
as an abstract base class using ABCMeta
. The object
indicates that Book
is a new-style class inheriting from the base object
class in Python.
The line def __init__(self, title, author)
is the constructor method for the class. It is automatically called when a new instance of Book
is created, initializing the title
and author
attributes of the instance.
Finally, @abstractmethod
indicates that the display
method is an abstract method. This means that any subclass of Book
must provide its own implementation of the display
method. The pass
keyword is used as a placeholder indicating where code will eventually go. If a subclass does not implement this method, it cannot be instantiated (you can't create objects of that subclass).
You can read more on abstract methods and the abc
module at https://docs.python.org/3/library/abc.html.
The code below where we will write the MyBook
class sets the variables for title
, author
, and price
to whatever input is provided by the user, with price
being cast from a string to an integer. It instantiates an instance of MyBook
called new_novel
and calls the display()
method.
So our first task is to create the MyBook
class to inherit from the Book
class. To do this, we just need to define the class and add the parent class as a parameter and add the __init__()
function, which will override the parent class's __init__()
function (more on this a bit):
def MyBook(Book):
def __init__(self, title, author):
Since we want our MyBook
class to have all of the properties and methods that are in the Book
class we'll use the super()
function. Then we'll add in the price
property, which will be specific only to our subclass. Don't forget to add it to the __init__()
function as a parameter as well:
def MyBook(Book):
def __init__(self, title, author, price):
super().__init__(title, author):
self.price = price
The next step is to implement the Book class' abstract display()
method. The challenge gives us the following output format:
Title: $title
Author: $author
Price: $price
Noting that the $
is prepended to variable names to indicate they are placeholders for variables.
I write the method as follows, using f-strings to produce the required output:
def display(title, author, price):
print(f"Title: {title}")
print(f"Author: {author}")
print(f"Price: {price}")
Here I'm thinking I'm all set, so I run the code and get the following error:
- Traceback (most recent call last):
- File "/tmp/submission/20231220/03/29/hackerrank-ff98319665ac0ee953b1fb5664e87cb3/code/Solution.py", line 27, in <module>
- new_novel.display()
- TypeError: MyBook.display() missing 2 required positional arguments: 'author' and 'price'
Personally, I like to debug and step through code to see where I went wrong so I'm going to paste the code into my Thonny IDE. I like Thonny for small code challenges like this because it doesn't require setting up a whole project just to run and step through code.
After stepping through the code, I can see exactly where and what the issue is:
I realize that I could also get this information from the error message itself, but in my experience, just stepping through and seeing what everything is doing at a granular level helps me figure out the problem more easily.
The message says that I'm missing two required positional arguments. Time to do some digging at this point since I'm not sure what that means. I checked out w3schools Python tutorial on inheritance. (P.S. I LOVE W3Schools).
After checking out the section for Adding Methods, I see where I went wrong adding in the variables as parameters instead of the self
keyword, which I now remember is what we do in Python for implementing methods in subclasses.
Success!
After running my code in the challenge code editor, I get the green success message. Challenge complete! 🎉
I hope you enjoyed this first post. I am new to blogging and one of my goals is to get better at it so if you have any questions or feedback, please feel free to leave a comment, or connect with me:
Twitter: @sarah_schlueter
Discord: sarahmarie73
Thanks for reading and happy coding!
Here's the final code for the challenge:
from abc import ABCMeta, abstractmethod
class Book(object, metaclass=ABCMeta):
def __init__(self,title,author):
self.title=title
self.author=author
@abstractmethod
def display(): pass
#Write MyBook class
class MyBook(Book):
def __init__(self, title, author, price):
super().__init__(title, author)
self.price = price
def display(self):
print(f"Title: {title}")
print(f"Author: {author}")
print(f"Price: {price}")
title=input()
author=input()
price=int(input())
new_novel=MyBook(title,author,price)
new_novel.display()
Posted on December 20, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.