class Book:
def __init__(self, title, last, first):
self._title = title #A
self._last = last #A
self._first = first #A
@property #B
def title(self): return self._title #B
#B
@property #B
def last(self): return self._last #B
#B
@property #B
def first(self): return self._first #B
def __str__(self):
return (f"{{TITLE: '{self._title}', LAST: '{self._last}', " #C
f"FIRST: '{self._first}'}}") #C36 OOP: Book Catalog
36.1 Iteration 1
36.1.1 Book Class
36.1.2 Catalogue Class
class Catalogue:
@staticmethod
def _equal_ignore_case(target_str, other_str):
if len(target_str) == 0:
return True
else:
return target_str.casefold() == other_str.casefold()
def __init__(self):
self._booklist = []
def add(self, title, last, first):
book = Book(title, last, first)
self._booklist.append(book)
def _is_match(self, book, target):
return ( Catalogue._equal_ignore_case(target.title,
book.title)
and Catalogue._equal_ignore_case(target.last,
book.last)
and Catalogue._equal_ignore_case(target.first,
book.first)
)
def find(self, target):
return [book for book in self._booklist
if self._is_match(book, target)
]36.1.3 Usage
def fill(catalogue): #A
catalogue.add("Life of Pi", "Martel", "Yann")
catalogue.add("The Call of the Wild", "London", "Jack")
catalogue.add("To Kill a Mockingbird", "Lee", "Harper")
catalogue.add("Little Women", "Alcott", "Louisa")
catalogue.add("The Adventures of Sherlock Holmes", "Doyle", "Conan")
catalogue.add("And Then There Were None", "Christie", "Agatha")
catalogue.add("Carrie", "King", "Stephen")
catalogue.add("It: A Novel", "King", "Stephen")
catalogue.add("Frankenstein", "Shelley", "Mary")
catalogue.add("2001: A Space Odyssey", "Clarke", "Arthur")
catalogue.add("Ender's Game", "Card", "Orson")
def search(catalogue, target): #B
print()
print("Find ", end="")
print(target)
matches = catalogue.find(target)
if len(matches) == 0:
print("No matches.")
else:
print("Matches:")
for book in matches:
print(" ", end="")
print(book)
def test(catalogue): #C
target = Book("Life of Pi", "Martel", "Yann")
search(catalogue, target)
target = Book("", "King", "")
search(catalogue, target)
target = Book("1984", "Orwell", "George")
search(catalogue, target)
target = Book("", "", "") #D
search(catalogue, target)
catalogue = Catalogue()
fill(catalogue)
test(catalogue) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[23], line 49 45 search(catalogue, target) 48 catalogue = Catalogue() ---> 49 fill(catalogue) 50 test(catalogue) Cell In[23], line 2, in fill(catalogue) 1 def fill(catalogue): #A ----> 2 catalogue.add("Life of Pi", "Martel", "Yann") 3 catalogue.add("The Call of the Wild", "London", "Jack") 5 catalogue.add("To Kill a Mockingbird", "Lee", "Harper") TypeError: Catalogue.add() takes 2 positional arguments but 4 were given
36.2 Iteration 2
36.2.1 Genre(Enum)
from enum import Enum
class Genre(Enum): #A
UNSPECIFIED = 0
ADVENTURE = 1
CLASSICS = 2
DETECTIVE = 3
FANTASY = 4
HISTORIC = 5
HORROR = 6
ROMANCE = 7
SCIFI = 8
def __str__(self): return self.name.lower()Genre.ADVENTURE<Genre.ADVENTURE: 1>
print(Genre.ADVENTURE)
print(Genre(1))adventure
adventure
# Iterate through all defined genres
for genre in Genre:
print(genre) unspecified
adventure
classics
detective
fantasy
historic
horror
romance
scifi
36.2.2 Attributes
class Attributes:
@staticmethod
def _equal_ignore_case(target_str, other_str): #D
if len(target_str) == 0:
return True
else:
return target_str.casefold() == other_str.casefold()
def __init__(self, title, last, first, year, genre):
self._title = title
self._last = last
self._first = first
self._year = year #C
self._genre = genre #C
@property
def title(self): return self._title
@property
def last(self): return self._last
@property
def first(self): return self._first
@property
def year(self): return self._year
@property
def genre(self): return self._genre
def is_match(self, target_attrs): #B
return (
Attributes._equal_ignore_case(target_attrs.title,
self._title)
and Attributes._equal_ignore_case(target_attrs.last,
self._last)
and Attributes._equal_ignore_case(target_attrs.first,
self._first)
and ( (target_attrs.year == 0)
or (target_attrs.year == self._year))
and ( (target_attrs.genre == Genre.UNSPECIFIED)
or (target_attrs.genre == self._genre))
)
def __str__(self):
return (f"{{TITLE: '{self._title}', LAST: '{self._last}', "
f"FIRST: '{self._first}', YEAR: {self._year}, " #E
f"GENRE: {self._genre}}}") #E36.2.3 Book & Catalogue
class Book:
def __init__(self, attributes):
self._attributes = attributes
@property
def attributes(self): return self._attributesclass Catalogue:
def __init__(self):
self._booklist = []
def add(self, attrs):
self._booklist.append(Book(attrs)) #A
def find(self, target_attrs):
return [book for book in self._booklist
if book.attributes.is_match(target_attrs) #B
]36.2.4 Usage
catalogue = Catalogue()
catalogue.add(Attributes("The Call of the Wild",
"London", "Jack",
1903, Genre.ADVENTURE))
catalogue.add(Attributes("To Kill a Mockingbird",
"Lee", "Harper",
1960, Genre.CLASSICS))
target_attrs = Attributes("Life of Pi", "Martel", "Yann",
2003, Genre.ADVENTURE)
search(catalogue, target_attrs)
Find {TITLE: 'Life of Pi', LAST: 'Martel', FIRST: 'Yann', YEAR: 2003, GENRE: adventure}
No matches.