And Now for the Conclusion: The Manor's Oak-Panelled Library and __getitem__()[Part 2]
The second in this two-part article on Python's `__getitem__()` special method
This post concludes the two-part article on __getitem__()
. Read the first part here: The Manor House, the Oak-Panelled Library, the Vending Machine, and Python's __getitem__() [Part 1]
That's it. I've had enough of this nonsense. I wasn't sure what bothered me more. Was it the constant humming of the vending machine drowning the centuries-old silence in the library? Or was it the aesthetic aberration of the brightly coloured items in this dull grey fridge piercing the otherwise perfect timeless golden hue of the rest of this room? Probably both.
I stood up, determined to make things right. Then I realised I didn't know how. I stood there for a minute or so until I got my inspiration. A tapestry was hanging on the wall at the other end of the library. I looked around. There was no one around. I pulled the tapestry down. I managed to stay on my feet as I wobbled under its weight.
A minute later, the vending machine had been transformed into a rather quaint, albeit slightly odd, tapestried cabinet.
And yes, I did pull the plug before completing the transformation. Bliss.
Here's the problem. The VendingMachine
class you wrote in Part 1 doesn't make much sense in this story anymore. After all, I saved the day by "resolving" the vending machine issue!
But there's still a whole library to explore. So let's write a new Library
class in Part 2 of this article.
What We Know So Far
In Part 1, we discussed the __getitem__()
special method and how it's linked to the square brackets notation used to fetch items from a data structure. The most common use case is with integers in the square brackets, such as with lists and other sequences. Part 1 also explored the use of two integers in the square brackets, separated by commas:
hideous_machine[2, 1]
This is equivalent to passing the tuple (2, 1)
as an argument to hideous_machine.__getitem__()
.
However, we can use other valid Python expressions in the square brackets as long as the __getitem__()
special method supports the resulting data types.
In this article, you'll write a class that can accept different types of data within the square brackets, and that fetches data accordingly.
Library Catalogue
You'll work on the Library
class, which contains a collection of books. You'll focus on defining the __getitem__()
special method to fetch books from the library. As this article focuses on the __getitem__()
special method, you'll use the square brackets notation on a Library
object. There are three ways we'd like to use the square brackets for this class:
Use an integer as an index. The books are stored sequentially in the library, so you can fetch a book using a number.
Use a string to search for an author name in full or in part.
Use a string to search for a book's name in full or in part.
Let's start writing the code to define the Library
class. You'll also need a simple Book
class to deal with the books:
The Book
class has three data attributes, .title
, .author
, and .publication_year
. You can expand this class to make it more useful, such as by dealing with checking a book out of the library, say. But this will do just fine for what we need for this article. You could even use a dataclass or a named tuple for this, but I'll use a standard class for clarity.
The main class for this article is Library
. It has a .books
data attribute that's a list. The method add_books()
adds Book
objects to the Library
instance. You can make this method more versatile if you wish by allowing it to also accept a single Book
instance as an argument. But I'll keep this method as it is in this article.
Let's create an instance of Library
and add several Book
instances to it:
You create nine Book
instances and a Library
instance called gorgeous_library
. The name is apt since the hideous vending machine is no longer there! You add the books to the library using add_books()
.
This code should show the nine books, one on each line, since you're unpacking gorgeous_library.books
and setting the separator to "\n"
in the print()
function:
<__main__.Book object at 0x7f97d01e4c70>
<__main__.Book object at 0x7f97d01e4c10>
<__main__.Book object at 0x7f97d01e4b20>
<__main__.Book object at 0x7f97d01e4a30>
<__main__.Book object at 0x7f97d01e49d0>
<__main__.Book object at 0x7f97d01e4970>
<__main__.Book object at 0x7f97d01e4910>
<__main__.Book object at 0x7f97d01e48b0>
<__main__.Book object at 0x7f97d01e4850>
But it does not. You need to add a __str__()
special method to the Book
class:
The output now shows the books in the library:
To Kill a Mockingbird by Harper Lee (1960)
1984 by George Orwell (1949)
Animal Farm by George Orwell (1945)
The Hitchhiker's Guide to the Galaxy by Douglas Adams (1979)
Harry Potter and the Philosopher's Stone by J.K. Rowling (1997)
Harry Potter and the Chamber of Secrets by J.K. Rowling (1998)
A Brief History of Time by Stephen Hawking (1988)
The Selfish Gene by Richard Dawkins (1976)
Cosmos by Carl Sagan (1980)
Next, we'll focus on crafting a __getitem__()
special method to meet all the requirements.