I have a homework assignment to create a "library" with a patron class and book class. This library should allow people to check out up to 3 books, and add a book to a patron's waitlist if the book is already checked out. Upon the books return, it should be automatically checked out to the first person on the waitlist. I can't seem to get the list to work. Here's my code:
class Patron(object):
def __init__(self,name,booksOut=0):
self._name=name
self._booksOut=booksOut
def getBooksOut(self):
return self._booksOut
def __str__(self):
result="Name: "+self._name+"\n"
result+="Books Out: "+str(self._booksOut)+"\n"
return result
class Book(object):
def __init__(self,title,author,owner=None):
self._title=title
self._author=author
self._owner=owner
self._queue=[] #Here is the empty list I'm using... but it doesn't seem to be working.
def setOwner(self,owner):
self._owner=owner
def getOwner(self):
return self._owner
def borrowMe(self, patron):
if self._owner != None:
return "This book is not available. You've been added to the queue.\n"
self._queue.append(patron)
print(str(self._queue)) #I can't even get the list to print, so I'm feeling like I didn't create it correctly
else:
if patron.getBooksOut()>=3:
return "You have too many books checked out!"
else:
self.setOwner(patron)
patron._booksOut+=1
return "You have successfully checked this book out."
def returnMe(self):
if len(self._queue)==0:
self.setOwner(None)
return "Your book has been returned."
else:
return "Your book has been given to: "+str(self._queue[0])
self.borrowMe(self._queue[0]) #Here is where I'm trying to automatically borrow the book to the first person in the waitlist
def __str__(self):
result="Title: "+self._title+"\n"
result+="Author: "+self._author+"\n"
if self._owner != None:
result+="Owner: "+str(self.getOwner())
else:
result+="Owner: None"
return result
def main():
"""Tests the Patron and Book classes."""
p1 = Patron("Ken")
p2 = Patron("Martin")
b1 = Book("Atonement", "McEwan")
b2 = Book("The March", "Doctorow")
b3 = Book("Beach Music", "Conroy")
b4 = Book("Thirteen Moons", "Frazier")
print(b1.borrowMe(p1))
print(b2.borrowMe(p1))
print(b3.borrowMe(p1))
print(b1.borrowMe(p2))
print(b4.borrowMe(p1))
print(p1)
print(b1)
print(b4)
print(b1.returnMe())
print(b2.returnMe())
print(b1)
print(b2)
I've #commented the parts containing the list creation (in the init for the book class) and where I tried to print the list to do some error checking (in the borrowMe method) and also where I am trying to automatically borrow the book to the first person on the waitlist/queue (in the returnMe method).
Any insight is appreciated.
if self._owner != None:
return "This book is not available. You've been added to the queue.\n"
self._queue.append(patron)
print(str(self._queue))
You are printing after return. Nothing will be executed after return. Change it to print. Also in Patron class, change __str__ to __repr__. Otherwise it will print a list of memory addresses. In addition, print(str(self._queue)) is redundant, you could print the list directly.
Related
I was trying to write a function in python to print out all the overlapping movie interests.
I wanted to write this program as a little classes and objects exercise. So this is what it looks like, right now:
def main():
class Person:
def __init__(self, Film):
self.Film = Film
like_it = "Film" , "Movie"
def likes(self, Film):
if (Film in like_it):
return Film
else:
print("no movies in common")
Person1 = Person("Movie")
print(Person1.likes)
I wanted to initialize different People as objects in the class "Person". The Program doesn't see any mistakes, but prints nothing. What is wrong here? Where should I look?
Thank you so much for your help!!
You aren't passing Film as an argument in the likes method.
Working with Classes
class Person:
def __init__(self, Film):
self.Film = Film
like_it = "Film" , "Movie"
def likes(self):
if (self.film in like_it):
return self.film
else:
return "no movies in common" #we are returning string instead of printing
Person1 = Person("Movie")
print(Person1.likes()) #likes is a method that has to be called
References:
Object Oriented Programming with python
Further Reading:
Converting methods to property
So I have list of objects in class and I need to print all different songs from one singer.
So far I have this code and I am not sure is it correct
Also I need to use recursion method
def allmusic(listofobjects, name):
nameandsurname=self.name
if(listofobjects.name==nameandsurname):
print(listofobjects.music)
return(listofobjects(music[1:]))
else:
return(listofobjects(name[1:]))
Also I need to print number of singers in that class and code I have is
def allmusic(listofobjects):
numberofsingers=0
for s in listofobjects:
numberofsingers+=1
return(listofobjects()[1:])
print(numberofsingers)
I think this is what you want. It recursively prints the all songs of a specific singer provided in the arguments. Here listOfMusic is the list of Music objects.
def PrintSinger(self, listOfMusic, name):
if(listOfMusic[0].nameOfSinger == name):
print(listOfMusic[0].music)
if(len(listOfMusic) == 1):
return
else:
return self.PrintSinger(listOfMusic[1:], name)
I'm trying to return variable name, but i keep getting this:
<classes.man.man object at (some numbers (as example:0x03BDCA50))>
Below is my code:
from classes.man import man
def competition(guy1, guy2, counter1=0, counter2=0):
.......................
some *ok* manipulations
.......................
if counter1>counter2:
return guy1
bob = man(172, 'green')
bib = man(190, 'brown')
print(competition(bob , bib ))
Epilogue
If anyone want to, explain please what I can write instead of __class__ in example below to get variable name.
def __repr__(self):
return self.__class__.__name__
Anyway, thank you for all of your support
There are different ways to approach your problem.
The simplest I can fathom is if you can change the class man, make it accept an optional name in its __init__ and store it in the instance. This should look like this:
class man:
def __init__(number, color, name="John Doe"):
self.name = name
# rest of your code here
That way in your function you could just do with:
return guy1.name
Additionnally, if you want to go an extra step, you could define a __str__ method in your class man so that when you pass it to str() or print(), it shows the name instead:
# Inside class man
def __str__(self):
return self.name
That way your function could just do:
return guy1
And when you print the return value of your function it actually prints the name.
If you cannot alter class man, here is an extremely convoluted and costly suggestion, that could probably break depending on context:
import inspect
def competition(guy1, guy2, counter1=0, counter2=0):
guy1_name = ""
guy2_name = ""
for name, value in inspect.stack()[-1].frame.f_locals.items():
if value is guy1:
guy1_name = name
elif value is guy2:
guy2_name = name
if counter1 > counter2:
return guy1_name
elif counter2 > counter2:
return guy1_name
else:
return "Noone"
Valentin's answer - the first part of it at least (adding a name attribute to man) - is of course the proper, obvious solution.
Now wrt/ the second part (the inspect.stack hack), it's brittle at best - the "variables names" we're interested in might not necessarily be defined in the first parent frame, and FWIW they could as well just come from a dict etc...
Also, it's definitly not the competition() function's responsability to care about this (don't mix domain layer with presentation layer, thanks), and it's totally useless since the caller code can easily solve this part by itself:
def competition(guy1, guy2, counter1=0, counter2=0):
.......................
some *ok* manipulations
.......................
if counter1>counter2:
return guy1
def main():
bob = man(172, 'green')
bib = man(190, 'brown')
winner = competition(bob, bib)
if winner is bob:
print("bob wins")
elif winner is bib:
print("bib wins")
else:
print("tie!")
Python prints the location of class objects in memory if they are passed to the print() function as default. If you want a prettier output for a class you need to define the __repr__(self) function for that class which should return a string that is printed if an object is passed to print(). Then you can just return guy1
__repr__ is the method that defines the name in your case.
By default it gives you the object type information. If you want to print more apt name then you should override the __repr__ method
Check below code for instance
class class_with_overrided_repr:
def __repr__(self):
return "class_with_overrided_repr"
class class_without_overrided_repr:
pass
x = class_with_overrided_repr()
print x # class_with_overrided_repr
x = class_without_overrided_repr()
print x # <__main__.class_without_overrided_repr instance at 0x7f06002aa368>
Let me know if this what you want?
I am creating a class structure in python for a city, that stores the name, country, population and language for a city, all of which are input by the user. The information shall then be printed.
I think that I may be successful in storing the information within the class structure (although this may be wrong as well), but I am unsuccessful in printing the information. Currently, I am receiving the error that int object is not subscriptable.
class User():
def _init_(self, username, password, email, numOfLogins):
User.username = username
User.password = password
User.email = email
User.numOfLogins = numOfLogins
#User Record Array Creation
def createUserArray(num , User):
UserArray = []
for x in range(num):
UserArray.append(User)
return UserArray
#User Record Array Population
def populateUserArray(num, UserArray):
for x in range(len(userArray)):
UserArray[x].username = str(input("Enter username."))
UserArray[x].password = str(input("Enter password."))
UserArray[x].email = str(input("Enter email address."))
UserArray[x].numOfLogins = int(input("Enter number of logins."))
return UserArray
#User Record Array Display
def displayUserArray(UserArray, num):
for x in range(len(userArray)):
print(UserArray[x].username, UserArray[x].password, UserArray[x].email, str(UserArray[x].numOfLogins))
#Top Level Program
numOfUsers = 3
userArray = createUserArray(numOfUsers, User)
userArray = populateUserArray(numOfUsers, userArray)
displayUserArray(numOfUsers, userArray)
The contents of the class should all be displayed at the end of the program, but at the minute my program crashes due to the error - int object is not subscriptable.
you can always implement the method : __str__(self) of an object , and then when you just print it with :
your_obj = User(...)
print your_obj
your __str__(self) will be called and you can return from it whatever you want to print.
for example:
def __self__(self):
return `this class has the following attributes: %s %s %s %s` % (self.username,self.password,self.email ,self.numOfLogins )
and this what will get print, i think it is more efficient and well coded to work like that and not creating a function that print each class attribute separately.
The cause of your error is quite simple and obvious: you defined the function as displayUserArray(UserArray, num) but call it with displayUserArray(numOfUsers, userArray) - IOW you pass the arguments in the wrong order.
This being said, almost all your code is wrong, you obviously don't get the difference between a class and instance and how to use a class to create instances. I strongly suggest you read at least the official tutorial, and check a couple other tutorial and/or example code on the topic of classes and instances.
I'm currently self-learning Python, and I'm reading 'Problem Solving with Algorithms and Data Structures' (Brad Miller, David Ranum). I've stumbled upon the basic example of inheritance. Although I can see what it does, I need an explanation, how it works actually. The Code is as follows:
class LogicGate:
def __init__(self,n):
self.name = n
self.output = None
def getName(self):
return self.name
def getOutput(self):
self.output = self.performGateLogic()
return self.output
class BinaryGate(LogicGate):
def __init__(self,n):
LogicGate.__init__(self,n)
self.pinA = None
self.pinB = None
def getPinA(self):
if self.pinA == None:
return int(input("Enter Pin A input for gate "+self.getName()+"-->"))
else:
return self.pinA.getFrom().getOutput()
def getPinB(self):
if self.pinB == None:
return int(input("Enter Pin B input for gate "+self.getName()+"-->"))
else:
return self.pinB.getFrom().getOutput()
def setNextPin(self,source):
if self.pinA == None:
self.pinA = source
else:
if self.pinB == None:
self.pinB = source
else:
print("Cannot Connect: NO EMPTY PINS on this gate")
class AndGate(BinaryGate):
def __init__(self,n):
BinaryGate.__init__(self,n)
def performGateLogic(self):
a = self.getPinA()
b = self.getPinB()
if a==1 and b==1:
return 1
else:
return 0
class OrGate(BinaryGate):
def __init__(self,n):
BinaryGate.__init__(self,n)
def performGateLogic(self):
a = self.getPinA()
b = self.getPinB()
if a ==1 or b==1:
return 1
else:
return 0
class UnaryGate(LogicGate):
def __init__(self,n):
LogicGate.__init__(self,n)
self.pin = None
def getPin(self):
if self.pin == None:
return int(input("Enter Pin input for gate "+self.getName()+"-->"))
else:
return self.pin.getFrom().getOutput()
def setNextPin(self,source):
if self.pin == None:
self.pin = source
else:
print("Cannot Connect: NO EMPTY PINS on this gate")
class NotGate(UnaryGate):
def __init__(self,n):
UnaryGate.__init__(self,n)
def performGateLogic(self):
if self.getPin():
return 0
else:
return 1
class Connector:
def __init__(self, fgate, tgate):
self.fromgate = fgate
self.togate = tgate
tgate.setNextPin(self)
def getFrom(self):
return self.fromgate
def getTo(self):
return self.togate
def main():
g1 = AndGate("G1")
g2 = AndGate("G2")
g3 = OrGate("G3")
g4 = NotGate("G4")
c1 = Connector(g1,g3)
c2 = Connector(g2,g3)
c3 = Connector(g3,g4)
print(g4.getOutput())
main()
I'm mostly doubted by the tgate.setNextPin(self) statement in Connector class __init__. Is it a method call? If it is, why is it called with just one parameter, when there are two actually required by the setNexPin function in UnaryGate and BinaryGate classes (self, source)? How does the fromgate variable ends up as the source arrgument? Does this statement 'initiliaze' anything actually, and what?
Next thing which troubles me is, for example, when I print(type(g4)) before declaring g4.getOutput(), I get <class '__main__.OrGate'>, but when the g4.getOutput() starts, and functions start calling each other, to the point of calling getPin function, if I put print (self.pinA) before return self.pinA.getFrom().getOutput(), I get the <__main__.Connector object at 0x2b387e2f74d0>, although self.Pin is a variable from g4 OrGate instance. How can one variable from one class instance can become object of another class, which isn't inheriting it? Does this have something with a work of setNextPin() function?
Can someone explain this to me as I am new to OOP and thorougly confused by this piece of code. Thank you.
Regarding your first question, tgate.setNextPin(self) is a method call. tgate is an object, presumably an instance of one of the gate types. When you access instance.method, Python gives you a "bound method" object, which works pretty much like a function, but which puts the instance in as the first argument when it is actually called. So, tgate.setNextPin(self) is really calling type(tgate).setNextPin(tgate, self)
Your second question seems to reflect a misunderstanding of what attributes are. There's no requirement that an object's attributes be of its own type. In the various LogicGate sub-classes, the pin/pinA/pinB attributes are either going to be None (signaling that the user should be prompted for an input value) or an instance of a Connector (or something else with a getFrom method). Neither of those values is a LogicGate instance.
As for where the Connector instance you saw came from, its going to be one of the c1 through c3 values you created. Connector instances install themselves onto a pin of their tgate argument, with the setNextPin call you were asking about in your first question. I can't really speak to the g4 gate you are looking at, as it seems to be different than the g4 variable created in your example code's main() function (it is a different type), but I suspect that it is working as designed, and it's just a bit confusing. Try accessing the pinX attributes via g4.pinA rather than inspecting them inside of the methods and you may have a bit less confusion.
Here's a bit of code with outputs that should help you understand things a bit better:
# create a few gates
g1 = AndGate("G1")
g2 = OrGate("G2")
# at this point, no connectors have been hooked up, so all pinX attrs are None:
print("G1 pins:", g1.pinA, g1.pinB) # "None, None"
print("G2 pins:", g2.pinA, g2.pinB) # "None, None"
# test that the gates work independently of each other:
print("G1 output:", g1.getOutput()) # will prompt for two inputs, then print their AND
print("G2 output:", g2.getOutput()) # will prompt for two inputs, then print their OR
# create a connection between the gates
c1 = Connector(g1, g2) # connects output of g1 to first available pin (pinA) of g2
# we can see that g2.pinA has changed
print("G2 pins after connection:", g2.pinA, g2.pinB)
# "<__main__.Connector object at SomeHexAddress>, None"
# now, if we get g2's output, it will automatically request g1's output via the Connector
print("G2 output:", g2.getOutput())
# will prompt for 2 G1 inputs, and one G2 input and print (G1_A AND G1_B) OR G2_B
If you want to play around with these classes more, you might want to add a __str__ (and/or __repr__) method to some or all of the classes. __str__ is used by Python to convert an instance of the class into a string whenever necessary (such as when you pass it as an argument to print or str.format). Here's a quick __str__ implementation for Connector:
def __str__(self):
return "Connector between {} and {}".format(self.fgate.name, self.tgate.name)