Writing a function to reshelve books where the Library attempts to reshelve a book currently held by the indicated Patron. The book is moved from patron's borroweds to the Library's available books list. I coded most of it, but I'm not sure if my loop is correct and I have no idea where to insert my missingIdError, any suggestions? Note: I also have a Patron Class and defined them already along with the ID so no need to worry about the missing class.
class DuplicateIdError (Exception):
def __init__(self, id, category = "Book" or "Patron"):
self.id = int(id)
self.category = str(category)
def __str__(self):
return 'duplicate {} ID: #{}'.format(self.category,self.id)
def __repr__(self):
return 'duplicate {} ID: #{}'.format(self.category,self.id)
class MissingIdError (LookupError):
def __init__(self, id, category = "Book" or "Patron"):
self.id = int(id)
self.category = str(category)
def __str__(self):
return 'duplicate {}: {}'.format(self.id, self.category)
def __repr__(self):
return 'duplicate {}: {}'.format(self.id, self.category)
class Library:
def __init__(self, books=None, patrons=None):
self.books = []
self.patrons = []
def __str__(self):
return "Library(<{}>, <{}>)".format(self.self.books, self.patrons)
def __repr__(self):
return "Library(<{}>, <{}>)".format(self.self.books, self.patrons)
#Returns None.
#Raises a DuplicateIdError if there's already a book in the library with that id#.
#Raises a MissingIdError if the patron or book wasn't found
def reshelve_book(self, patron_id, book_id):
for patron in self.patrons:
for book in self.books:
try:
if book.book_id == book_id:
raise DuplicateIdError(book_id,"Book")
elif book.book_id != book_id:
self.books.append(book)
book.borroweds.remove(book)
Just a couple of simple guards would give you the other exception:
def reshelve_book(self, patron_id, book_id):
if patron_id not in self.patrons:
raise MissingIdError(patrod_id, 'Patron')
I don't understand book.borroweds.remove(book) but presumable you need to test book_id has been borrowed.
Do you really need a loop?
def reshelve_book(self, patron_id, book_id):
if patron_id not in self.patrons:
raise MissingIdError(patrod_id, 'Patron')
if book_id in self.books:
raise DuplicateIdError(book_id,"Book")
try:
book = self.patrons[patron_id].borrowed_books[book_id]
except KeyError:
raise MissingIdError(book_id, 'Book')
self.books[book_id] = book
del self.patrons[patron_id].borrowed_books[book_id]
BTW: your constructors for the exceptions don't do what I think you think it does:
def __init__(self, id, category = "Book" or "Patron"):
Is equivalent to do:
def __init__(self, id, category = True):
I would just avoid putting a default arg for category:
def __init__(self, id, category):
Related
I am an IT student and I'm completely new with Python. In a workshop I worked on there were a few lines in between that I don't really understand how they work and their purpose in the code. Those lines come from a fellow student who successfully ran it and I would like to fully understand. Thank you!
Overall, this is my code:
class AcademicPublication():
def __init__(self, title, year):
self.__year = year
self.__title = title
self.__authors = []
def addAuthor(self, author_name):
self.author_name = author_name
self.__authors.append(author_name)
def getReference(self):
return f"{self.__authors}, {self.__authors}({self.__year}): {self.__title}."
class Conference():
def __init__(self, acronym, name):
self.acronym = acronym
self.name = name
self.paper = []
def addPaper(self, conference_paper):
self.paper.append(conference_paper)
conference_paper.Conference = self
conference_paper.acronym = self.acronym
conference_paper.name = self.name
class ConferencePaper(AcademicPublication):
def __init__(self, title, year):
super().__init__(title, year)
def getReference(self):
return super().getReference() + '. In Proceedings of ' + str(self.name) + str(self.acronym)
And I'm struggling with this part:
self.paper.append(conference_paper)
conference_paper.Conference = self
conference_paper.acronym = self.acronym
conference_paper.name = self.name
At first I thought conference_paper is a class attribute, but there was no definition before in the code, and I did some research but I didn't find anything about a parameter from this method accessing another method's parameter.
I was trying to write a code and check it with pytest. I thought I did everything ok, but I got a problem. After writing this, I want to check it with method of class Person. When I tried to use method id the function ends and I got the output:
TypeError: 'str' object is not callable
My code:
class Person:
def __init__(self, id, name, sex, birth_date):
self.name = name
self.id = id
self.sex = sex
self.birth_date = birth_date
def __str__(self):
return f'{self.name} born {self.birth_date} with {self.sex} has {self.id}'
def name(self):
return self.name
def sex(self):
return self.sex
def id(self):
return self.id
def date_of_birth(self):
return self.birth_date
def read_from_file(file_handle):
people = []
reader = csv.DictReader(file_handle)
for row in reader:
id = row['id']
name = row['name']
sex = row['sex']
birth_date = row['birth_date']
person = Person(id, name, sex, birth_date)
print(person.id())[Error in this line]
people.append(person)
return people
def test_files():
with open('people.txt', 'r') as people_txt:
people = read_from_file(people_txt)
Example of line of people.txt:
id,name,sex,birth_date
1,Doralyn Dovermann,Female,27/10/2005
2,Rickert Petschel,Male,10/7/2018
3,Whitney Girardoni,Female,7/3/1932
That error occurs when you try to call a string as if it were a function. In your code you call person.id(), but person.id is not a function. If you want to print the contents of the string attribute, just do print(person.id).
I am working on a web-scraping project (monster.com). Everything is working, but I wanted to display the the relevant info on the same line (heading, company, location, date), but I can't I tried end='', but it doesn't work
from locators.jobs_locators import JobsLocators
class JobsParser:
def __init__(self, parent):
self.parent = parent
def __repr__(self):
return f"{self.heading}, at {self.company}, located in {self.location}, posted {self.date}"
#property
def heading(self):
return self.parent.select_one(JobsLocators.HEADING).string
#property
def company(self):
try:
return self.parent.select_one(JobsLocators.COMPANY).string
except:
return self.parent.select_one(JobsLocators.COMPANY1).string
#property
def location(self):
try:
return self.parent.select_one(JobsLocators.LOCATION).string
except:
return self.parent.select_one(JobsLocators.COMPANY1).string
#property
def date(self):
return self.parent.select_one(JobsLocators.DATE).string
I want to code movie classification class, which can find (based on some criterias), add and print movies.
Here is my code:
class Movie:
def __init__(self,name,director,year,location):
self.name = name
self.director = director
self.year = year
self.location = location
self.information = {'name':self.name,'director':self.director,'year':self.year,'location':self.location}
def get_name(self):
return self.name
def get_director(self):
return self.director
def get_year(self):
return self.year
def get_location(self):
return self.location
def get_information(self):
return self.information
def __str__(self):
return f"Name = {self.name},director = {self.director},year = {self.year},location = {self.location}"
class Classification:
def __init__(self):
self.movie_list = []
def length(self):
return len(self.movie_list)
def __getitem__(self,key):
if isinstance(self.movie_list,slice):
return self.movie_list[key]
def add_movie(self,movie):
self.movie_list.append(movie)
def print_movie(self):
for movie in self.movie_list:
print(movie)
def find_movie(self,**kwargs):
check_list = []
for movie in self.movie_list:
for name,value in kwargs.items():
if movie.get_information()[name] == value:
check_list.append(True)
else:
check_list.append(False)
if all(item == True for item in check_list):
print(movie)
check_list.clear()
Here i have a class Movie and Classification; Classification has only 1 attribute, which is a list of movies. But i have two problems:
a = Movie('Matrix','Dan Yefimov','1999','New York')
b = Movie('Legend','Mak Markus','2005','Kiev')
clasif = Classification()
clasif.add_movie(a)
clasif.add_movie(b)
clasif.find_movie(location = 'New York')
find_movie() works for the first movie (a in our case) in the list. But for the second one it prints nothing, even when I enter correct parameters for a search.
Slicing doesn't work. There is no error message, it just prints nothing.
Can you help me with my problems?
P.S I would like also to hear some general advices about improving of my code.
By removing the unnecessary methods, we can shorten the code considerably. We can also just pass __getitem__ through to the list. I would also use __len__ over defining a length method.
class Movie:
def __init__(self,name,director,year,location):
self.name = name
self.director = director
self.year = year
self.location = location
def __str__(self):
return f"Name = {self.name},director = {self.director},year = {self.year},location = {self.location}"
class Classification:
def __init__(self):
self.movie_list = []
def __len__(self): # __len__ lets you do len(classif)
return len(self.movie_list)
def __getitem__(self,key):
return self.movie_list[key]
def add_movie(self,movie):
self.movie_list.append(movie)
def print_movie(self):
for movie in self.movie_list:
print(movie)
def find_movie(self,**kwargs):
for movie in self.movie_list:
if all(hasattr(movie, k) and getattr(movie, k) == v for k, v in kwargs.items()):
print(movie)
Here is a version of your code will a little less code:
class Movie:
ATTRIBUTES = ('name', 'director', 'year', 'location')
def __init__(self, name, director, year, location):
self.name = name
self.director = director
self.year = year
self.location = location
def __str__(self):
return ', '.join(
'{} = {}'.format(attr_name, getattr(self, attr_name))
for attr_name in self.ATTRIBUTES)
class Classification:
def __init__(self):
self.movie_list = []
def __len__(self):
return len(self.movie_list)
def __getitem__(self, key):
return self.movie_list[key]
def add_movie(self, movie):
self.movie_list.append(movie)
def print_movies(self):
for movie in self.movie_list:
print(movie)
def find_movies(self, **kwargs):
for movie in self.movie_list:
do_print = True
for attr_name, attr_value in kwargs.items():
if attr_name in Movie.ATTRIBUTES:
if getattr(movie, attr_name) != attr_value:
do_print = False
if do_print:
print(movie)
I added a class attribute called ATTRIBUTES to Movie; this is used in Movie.__str__() and also in Classification.find_movies(). It is a suggestion to avoid repeating the attributes a lot in the code.
In the method Classification.find_movies() I check that it is a valid attribute before I compare it to the movie instance. Invalid parameters are ignored, but you could change the code so that invalid parameters automatically cause the movies to not be printed (all will be excluded).
In my project I'm using code from http://djangosnippets.org/snippets/562/ and I'm encountering some problems.
When I use my own ChainableQuerySetManager and try to create an object through a related object I get a recursion error.
ChainableQuerySetManager source:
class ChainableQuerySetManager(models.Manager):
def __init__(self, qs_class=models.query.QuerySet):
super(ChainableQuerySetManager,self).__init__()
self.queryset_class = qs_class
def get_query_set(self):
return self.queryset_class(self.model)
def __getattr__(self, attr, *args):
try:
return getattr(self.__class__, attr, *args)
except AttributeError:
return getattr(self.get_query_set(), attr, *args)
Extended query set:
class ExtendedQuerySet(models.query.QuerySet):
def get_or_None(self, *args, **kwargs):
result = None
try:
result = self.get(*args, **kwargs)
except ObjectDoesNotExist:
pass
return result
And test models:
class ParentObject(models.Model):
value = models.IntegerField(default=0)
def count_someobjects(self):
return self.someobjects.count()
def create_someobject_throw_related(self):
return self.someobjects.create()
def create_someobject(self):
return SomeObject.objects.create(parent=self)
class SomeObject(models.Model):
parent = models.ForeignKey(ParentObject, related_name='someobjects')
value = models.IntegerField(default=1)
objects = ChainableQuerySetManager(ExtendedQuerySet)
Test Case looks like:
class ExtendedQuerySetTests(TestCase):
def setUp(self):
self.parent = ParentObject.objects.create()
def test_create_someobject_in_parent(self):
someobject = self.parent.create_someobject_throw_related()
I would appreciate your help.
Full source can be found at https://github.com/RANUX/django-simptools
I recently had a similar issue. Try replacing self.__class__ with ChainableQuerySetManager in your query manager. I never quite sorted out exactly why this was the issue, but it did solve things for me.