Why is the if clause being skipped? - python

# in file contactList.py
import contact
class ContactList:
def __init__(self):
self.added = True
self.list = []
def add(self, newContact):
added = 1
self.list.append(newContact)
def __str__(self):
if (self.added == True):
returnedString = ""
for contact in self.list:
returnedString = returnedString + "\n" + str(contact)
return returnedString
def find(self, name):
self.name = name
for contact in self.list:
if self.name == (str(contact))[0]: # I also tried if self.name in str(contact)
return str(contact)
else:
return "Invalid input"
if __name__ == "__main__":
myFriends = ContactList()
friend1 = contact.Contact("Mickey", "650-345-3333", "Mickey#disneyland.com", "Disneyland, California")
friend2 = contact.Contact("Minnie", "650-345-3344", "Minnie#disneyworld.com", "Disneyworld, Florida")
friend3 = contact.Contact("Donald", "650-345-3333", "Donald#EuroDisney.com", "EuroDisney, France")
myFriends.add(friend1)
myFriends.add(friend2)
myFriends.add(friend3)
print (myFriends)
print (myFriends.find("Mickey"))
I'm wondering why the last call, print (myFriends.find("Mickey")), is not be iterated by the shell; instead, it's skipped no matter what I put in the parameter. For example, when I enter "Mickey", "Minnie", or "Donald" in the parameter, I'm supposed to get the corresponding personal information about them, but the "if" clause under the find() function is never iterated. What's the problem here? Besides, since it was a snippet code to which I added find(), I'm not really sure what the purpose of the self.added = True in __init__ and the added = 1 in add().
Below is the contact() imported to this file contactList.py
#in file contact.py
class Contact:
"""
One object of class Contact represents one person's contact info.
"""
def __init__(self, name, phone, email, streetAddress):
self.name = name
self.phone = phone
self.email = email
self.streetAddress = streetAddress
def __str__(self):
return "%s\n%s\n%s\n%s\n" % (self.name, self.phone,self.email,self.streetAddress)
if __name__ == "__main__":
friend1 = Contact("Mickey", "650-345-3333", "Mickey#disneyland.com", "disneyland, CA")
print (friend1)

Your code as it is written will only check the first contact in the list. I'll just repeat what you have written here for clarity:
def find(self, name):
self.name = name
for contact in self.list:
if self.name == (str(contact))[0]:
return str(contact)
else:
return "Invalid input"
Now to be extra clear let's just keep the important parts:
if :# some condition is true
return str(contact)
else: # some condition is false
return "Invalid input"
As you can see in either case you get a return value. So you're not going to be finding your value if it's not the first one in your list, doesn't matter if the "some condition" referred to above is correct or buggy.
Edit: to be crystal clear, you need to put your failure condition (returning "invalid input" or whatever) after the for loop, not inside of it. This is left as an exercise to the reader.
Now as for the condition you're checking, based on the structure of the Contact class you posted I'd guess the right check would be:
if name == contact.name:
Nice and neat like python should be :)
Good luck

(str(contact))[0] gives the first character of the string representation of contact. So one character is never equal to a name with more than one character.
If contact has index access and the first index is actually the name, you should write:
def find(self, name):
for contact in self.list:
if name == contact[0]:
return contact
else:
return "Invalid input"

Why do you put if statement in (). you dont have to do it.
if self.added == True:
This way it will be enought.
Try this:
if self.name == str(contact[0])
Instead of this
if self.name == (str(contact))[0]

Related

How to call object of class by input?

I am generating a class of persons and want to get information about a certain person by input. I would like to use the str funtction because I am trying to understand it better. My Idea goes as follows:
class Person:
__init__(self, f_name, l_name):
self.f_name = f_name
self.l_name = l_name
__str__(self):
return "The persons full name is:" + f_name + l_name
person1 = Person(Peter, Punk)
person2 = Person(Mia, Munch)
person = input("What persons full name would you like to know?")
print(person) #I am aware that this just fills in the string saved in person, but how do I connect it to the variable?
another idea was to do it as follows:
#class stays the same except:
__init__(self, f_name, l_name):
self.f_name = f_name
self.l_name = l_name
list.append(self)
#and then for the main:
list = []
person1 = Person(Peter, Punk)
person2 = Person(Mia, Munch)
person = input("What persons full name would you like to know?")
index = list(person)
print(list[index])
Thankful for any edvice since I am obviously new to Python :D
I think OP has some concept problems here which this answer may go some way to help with.
Start by building a robust class definition. Simple in this case as there are just 2 attributes. Note the use of setters, getters and str, repr and eq dunder overrides.
A small function that checks if a given Person can be found in a list of Persons and reports accordingly.
Create a list with 2 different Person instances
Create another Person that is known not to match anything already in the list.
Run check()
Modify the 'standalone' Person to make it equivalent to something previously constructed.
Run check()
class Person:
def __init__(self, forename, surname):
self._forename = forename
self._surname = surname
#property
def forename(self):
return self._forename
#forename.setter
def forename(self, forename):
self._forename = forename
#property
def surname(self):
return self._surname
#surname.setter
def surname(self, surname):
self._surname = surname
def __str__(self):
return f'{self.forename} {self.surname}'
def __repr__(self):
return f'{self.forename=} {self.surname=}'
def __eq__(self, other):
if isinstance(other, type(self)):
return self.forename == other.forename and self.surname == other.surname
return False
def check(list_, p):
if p in list_:
print(f'Found {p}')
else:
print(f'Could not find {p}')
plist = [Person('Pete', 'Piper'), Person('Joe', 'Jones')]
person = Person('Pete', 'Jones')
check(plist, person)
person.surname = 'Piper'
check(plist, person)
Output:
Could not find Pete Jones
Found Pete Piper
You probably want a mapping between a name and an object. This is what Python's dict dictionary structure is for:
people = {} # an empty dictionary
people[f'{person1.f_name} {person1.l_name}'] = person1
people[f'{person2.f_name} {person2.l_name}'] = person2
This is creating a string of the first and last name.
You can then lookup the Person object using the full name:
print(people['Peter Punk'])
You could do this with list comprehension like so (also allowing multiple people to have the same first name)
class Person:
__init__(self, f_name, l_name):
self.f_name = f_name
self.l_name = l_name
__str__(self):
return "The persons full name is:" + f_name + l_name
personList= []
personList.append(Person(Peter, Punk))
personList.append(Person(Mia, Munch))
personName = input("What persons full name would you like to know?")
print([str(person) for person in personList if person.f_name == personName])

I dont know where I'm going wrong trying to create an object in a subclass through inputs

I've tried many different things so it's a little all over the place, please help
I've been able to make the first class and then in a different file create some objects for it, but for this subclass I need to use user input and I just can't figure it out.
I have made it so the shift input has to be a 1 or 2 for a day or night shift, I just don't have the knowledge for this.
class Employee:
def __init__(self, name, id, dept, title):
self.__name = name
self.__id = id
self.__dept = dept
self.__title = title
def get_name(self):
return self.__name
def get_id(self):
return self.__id
def get_dept(self):
return self.__dept
def get_title(self):
return self.__title
def __str__(self):
result = ""
result += "Name: " + self.get_name() + "\tID Number: " + str(self.get_id()) + \
"\tDepartment: " + self.get_dept() + "\tJob Title:" + self.get_title()
return result
class ShiftEmployee(Employee):
def __init__(self, name, id, dept, title, shift, pay):
Employee.__init__(self, name, id, dept, title)
self.__shift = shift
self.__pay = pay
#classmethod
def inputs(self):
self.__name = input("Enter name: ")
self.__id = input("Enter ID number: ")
self.__dept = input("Enter department: ")
self.__title = input("Enter Jobe title: ")
self.__shift = input("Enter shift: ")
self.__pay = input("Enter hourly pay: ")
#set_shift(self, shift):
#self.__shift = shift
#def set_pay(self, pay):
#self.__pay = pay
def get_shift(self, shift):
if self.__shift == 1:
return "Day"
elif self.__shift == 0:
return "Night"
else:
return "Invalid entry"
def get_pay(self, pay):
return self.__pay
def __str__(self):
result = ""
#result += Employee.__str__(self)
result += "Name: " + self.get_name(ShiftEmployee) + "\tID Number: " + str(self.get_id(ShiftEmployee)) + \
"\tDepartment: " + self.get_dept(ShiftEmployee) + "\tJob Title:" + self.get_title(ShiftEmployee) + \
"\tShift: " + self.get_shift(ShiftEmployee) + "\tHourly Pay: " + str(self.get_pay(ShiftEmployee))
return result
shift_emp = ShiftEmployee
shift_emp.inputs()
print(shift_emp.__str__(ShiftEmployee))
Don't use a classmethod because
A class method is a method that’s shared among all objects.
Though python itself does not force this behavior, your use of self in the inputs definition indicates that you are not doing what you think. the parameter is traditionally named cls in #classmethod-annotated methods, because the object you're referring to inside the body is not an instance of the class, but the class object itself. This means if you have multiple ShiftEmployee objects, they're going to be writing their data to the same variables. This is not what you want to happen.
you are not instantiating a ShiftEmployee object with shift_emp = ShiftEmployee, but rather assigning the class to the variable shift_emp, which is not what you want to do. so if you remove the #classmethod annotation, I think what you want is
shift_emp = ShiftEmployee() # __init__ gets called when you use this constructor invocation
shift_emp.inputs()
print(shift_emp)
Your __str__ methods don't make a lot of sense. You are passing the class object to each getter, which doesn't seem like it's what you'd want to do. The class object defines the class, what you want are the instances of the class. It's an important, if initially confusing distinction. Posting the error you get would help, but here's what I would expect the methods to look like. I'm not using the getters, because this is internal access, but you can use them instead of directly referring to the state variables if you prefer.
# Employee
def __str__(self):
return f"Name: {self.__name} ID Number: {self.__id} Department: {self.__dept} Job Title: {self.__title}"
# ShiftEmployee
def __str__(self):
return super(ShiftEmployee, self).__str__() + f" Shift: {self.__shift} Hourly Pay: {self.__pay}"
So what's going on here? For one thing, we use format strings because they are easier to work with and exactly the thing you wanted. Then we're using the superclass (Employee) to provide the shared functionality, and using the descendent class to enrich with the ShiftEmployee-only data. I skipped the accessor methods because they're redundant when accessing "private" data from inside the class members. Note that this won't quite do what you expect, either, w.r.t. the shift value that gets printed -- it's going to print the int, not "Night" or "Day". This is where your accessor method comes into play, except that your accessor has an extraneous parameter, shift. So you'd have to remove that value.
Please use the following way to initialize the class and printing the class,
shift_emp = ShiftEmployee() # Added Parenthesis
shift_emp.inputs()
print(str(shift_emp)) # Pass class object to inbuilt str() method to get output from __str__() method from class

How iterate through a list of class attributes and change their values?

I am trying to create a function, that if the user did not enter any value in input field then it sets the text value to 0 or to any other number.
value_text = [self.trig_side_a_value.text, self.trig_side_b_value.text, self.trig_side_c_value.text, self.trig_angle_A_value.text, self.trig_angle_B_value.text, self.trig_angle_C_value.text]
for i in value_text:
if i == "":
i = "0"
else:
pass
Thanks in advance!
OK, so there is quite a bit wrong here. I will try to answer this with as much explanation as possible.
One thing that is wrong:
value_text = [self.trig_side_a_value.text, self.trig_side_b_value.text, self.trig_side_c_value.text, self.trig_angle_A_value.text, self.trig_angle_B_value.text, self.trig_angle_C_value.text]
for i in value_text:
if i == "":
i = "0"
This creates a list value_text and populates it with copies of the text attributes. Changing what is in the list does not affect the elements of self..text.
What needs to happen is that you need to iterate through the attributes of the class, setting each attributes' text member:
Here is a solution:
class TextContainer():
""" This is a class with just one attribute 'text' """
def __init__(self, text=""):
self.text = text
class TestClass():
""" This class contains a set of TextContainer objects as its attributes. """
def __init__(self):
self.trig_side_a_value = TextContainer("a")
self.trig_side_b_value = TextContainer("b")
self.trig_side_c_value = TextContainer()
self.trig_angle_A_value = TextContainer("A")
self.trig_angle_B_value = TextContainer("B")
self.trig_angle_C_value = TextContainer()
def test_me(self):
""" Test the setting of each attribute """
for attr, container in self.__dict__.items():
if not container.text:
container.text = "0"
def __str__(self):
""" Returns a string representation of the class """
return "TestClass: ({}, {}, {}, {}, {}, {})".format(
self.trig_side_a_value.text,
self.trig_side_b_value.text,
self.trig_side_c_value.text,
self.trig_angle_A_value.text,
self.trig_angle_B_value.text,
self.trig_angle_C_value.text)
def main():
test = TestClass()
test.test_me()
print(test)
if __name__ == '__main__':
main()
Hope that helps. Others, please correct my usage of the __dict__ - I'm some shaky ground here.

Python :TypeError: this constructor takes no arguments

When the user enters an email address, and the program reads the email and display it according to its criteria (e.g yeo.myy#edu.co), like criteria:
username is yeo.myy
domain is edu.co
I know its something to do with the "#".
this is the code
class Email:
def __int__(self,emailAddr):
self.emailAddr = emailAddr
def domain(self):
index = 0
for i in range(len(emailAddr)):
if emailAddr[i] == "#":
index = i
return self.emailAddr[index+1:]
def username(self):
index = 0
for i in range(len(emailAddr)):
if emailAddr[i] == "#" :
index = i
return self.emailAddr[:index]
def main():
emailAddr = raw_input("Enter your email>>")
user = Email(emailAddr)
print "Username = ", user.username()
print "Domain = ", user.domain()
main()
this is the error I got:
Traceback (most recent call last):
File "C:/Users/Owner/Desktop/sdsd", line 29, in <module>
main()
File "C:/Users/Owner/Desktop/sdsd", line 24, in main
user = Email(emailAddr)
TypeError: this constructor takes no arguments
def __int__(self,emailAddr):
Did you mean __init__?
def __init__(self,emailAddr):
You're also missing a couple selfs in your methods, and your returns are improperly indented.
def domain(self):
index = 0
for i in range(len(self.emailAddr)):
if self.emailAddr[i] == "#":
index = i
return self.emailAddr[index+1:]
def username(self):
index = 0
for i in range(len(self.emailAddr)):
if self.emailAddr[i] == "#" :
index = i
return self.emailAddr[:index]
Result:
Username = yeo.myy
Domain = edu.co
Incidentally, I recommend partition and rpartition for splitting a string into two pieces on a given separator. Sure beats keeping track of indices manually.
def domain(self):
return self.emailAddr.rpartition("#")[2]
def username(self):
return self.emailAddr.rpartition("#")[0]
This error may happen if you type def _init_ with a single underline instead of def __init__ with double underlines before and after init.
class Employee:
def __init__(self,Name,Age,Salary,Gender):
self.Name = Name
self.Age = Age
self.Salary= Salary
self.Gender = Gender
def show_employee_deatils(self):
print("Name of the employee is ",self.Name)
print("Age of the employee is ",self.age)
print("Salary of the employee is ",self.salary)
print("gender of the employee is ",self.gender)
e1 = Employee('Shubham',25,25000,'male')
e1. show_Employee_deatils( )

Creating a list within an object (book/patron waitlist)

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.

Categories