How to call object of class by input? - python

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])

Related

Create a method that lists instances that were set to True in a previous class

I have the following code that records job candidates' personal details in a class Employee:
class Employee:
def __init__(self, name, role, id):
self.name = name
self.role = role
self.id = id
self.interviewed = False
def __str__(self):
text = f'Candidate {self.name}; {self.id}. '
if self.interviewed == False:
return text + 'Not interviewed yet.'
else:
return text + 'Interviewed.'
def interview(self):
self.interviewed = True
I also have another class Database that lists all the candidates in a database for a particular employer:
class Database:
def __init__(self, company, employer):
self.company = company
self.employer = employer
self.candidates = []
def __str__(self):
text = f'{The hiring company is {self.company} and the employers name is {self.employer}'
return text
def add_candidate(self, candidate):
self.candidates.append(candidate)
Now, if we record personal details of two candidates in the class Employee and add them to the class Database using the method add_candidate, how do I create a new method called list_interviewed_candidates(self) in the class Database that will print all candidates that have self.interviewed set to True?
This is what I tried:
class Database:
def __init__(self, company, employer):
self.company = company
self.employer = employer
self.candidates = []
def __str__(self):
text = f'{The hiring company is {self.company} and the employers name is {self.employer}'
return text
def add_candidate(self, candidate):
self.candidates.append(candidate)
def list_interviewed_candidates(self):
for employee in self.candidates:
if employee.interviewed == True:
return employee
But that doesn't work. I have also tried list comprehension but it seems I just cannot access the boolean value that was set in the first class. Ideally, the output should look something like this:
database1 = Database('Google', 'Jack H')
print(database1)
'The hiring company is Google and the employers name is Jack H'
candidate1 = Employee('Anna S', 'web-designer', 12)
database1.add_candidate(candidate1)
print(database1.list_interviewed_candidates())
[]
candidate1.interview()
print(database1.list_interviewed_candidates())
['Candidate Ana S; 12 - Interviewed']
In your Database.list_interviewed_candidates method you are returning the first employee that was interviewed. Keep in mind that return exits from the current function (method in this case) as soon as is hit.
So it starts looking at your candidates and as soon as one interviewed is found, it returns that one.
You probably want to gather them all in a list and return that:
def list_interviewed_candidates(self):
retval = []
for employee in self.candidates:
if employee.interviewed == True:
retval.append(employee)
return retval
Something pretty interesting you could also use is yield:
def list_interviewed_candidates(self):
for employee in self.candidates:
if employee.interviewed == True:
yield employee
Which... you can try by doing:
print(list(database1.list_interviewed_candidates()))
Pretty cool. This opens the really fun world of iterators!
A list comprehension works, but realize __str__ is used by print but __repr__ is used for items displayed in a list. __repr__ is also used if __str__ isn't defined.
Try the following, but change __str__ to __repr__ in Employee:
def list_interviewed_candidates(self):
return [employee for employee in self.candidates if employee.interviewed]
Then:
database1 = Database('Google', 'Jack H')
print(database1)
candidate1 = Employee('Anna S', 'web-designer', 12)
candidate2 = Employee('Mark T', 'pythonista', 13)
database1.add_candidate(candidate1)
database1.add_candidate(candidate2)
print(database1.list_interviewed_candidates())
candidate1.interview()
candidate2.interview()
print(database1.list_interviewed_candidates())
Outputs:
The hiring company is Google and the employers name is Jack H
[]
[Candidate Anna S; 12. Interviewed., Candidate Mark T; 13. Interviewed.]
Customize __str__ and __repr__ individually if you want differing output between direct print of Employee and how it is displayed in a list.

Editable Callers for Class Attributes - Python

I am working on a mock Student Database using OOP in python, and I am trying to use a function to search for certain parameters of a Class.
In the following example, School is a large class that holds instances of Students as one of its arguments. Hence (For Student in School.Student)
found_list = []
class Student():
def __init__(self, name, age, gender, name_of_school, class_type):
self.name = name
self.age = age
self.gender = gender
self.name_of_school = name_of_school
self.class_type = "S"
Example_Student = Student("Joseph", 8, "male", "The School", "S")
gender_to_be_found = input("Enter the gender to be searched for ")
for Student in School.Student:
if Student.gender == gender_to_be_found:
found_list.append(Student)
This works as a principle but I am wanting to do it in the below format, so I can search for various attributes of a Class through one function
def search_for(value_to_be_found, values_to_searched_from, end_list, class_argument):
if end_list != values_to_searched_from:
for possible_targets in value_to_be_found:
for possible_matches in values_to_searched_from:
try:
if possible_targets == possible_matches.class_argument:
end_list.append(possible_matches)
except:
pass
else:
for possible_targets in value_to_be_found:
for possible_matches in values_to_searched_from:
try:
if possible_targets != possible_matches.class_argument:
end_list.remove(possible_matches)
except:
pass
so that I can pass in the (class_argument) "gender"
and automatically search for any Student.gender that matches my value_to_be_found
search_for("Joseph", School.Student, found_list, "name")
Clearly this proposed method (above) is non-functional, but I feel like there is a way to do this that I have not managed to quite achieve.
This error is produced:
AttributeError: object has no attribute 'class_argument'
Thanks in advance for any help :)
You could add a search function to School, using getattr to access attributes of an object:
class Student():
def __init__(self, name, age, gender, name_of_school, class_type):
self.name = name
self.age = age
self.gender = gender
self.name_of_school = name_of_school
self.class_type = "S"
class School:
def __init__(self):
self.students = []
def add(self, student):
self.students.append(student)
def search(self, value, search_attribute):
result = []
for s in self.students:
student_value = getattr(s, search_attribute, None)
if student_value == value:
result.append(s)
return result
s1 = Student("Joseph", 8, "male", "The School", "S")
s2 = Student("Joseph2", 9, "male", "The School", "S")
s3 = Student("Joseph3", 10, "male", "The School", "S")
s = School()
s.add(s1)
s.add(s2)
s.add(s3)
print(s.search("Joseph", "name"))
print(s.search(10, "age"))
print(s.search("gender", "binary"))
print(s.search("The School", "name_of_school"))
Out:
[<__main__.Student object at 0x107c19fd0>]
[<__main__.Student object at 0x107c19ee0>]
[]
[<__main__.Student object at 0x10ab16fd0>, <__main__.Student object at 0x10ab16fa0>, <__main__.Student object at 0x10ab16ee0>]

I need to figure out how to save the user input as the new variables, not sure what to do from here

#I need to figure out how to save the user input as the new variables, not sure what to do from here.
class Person:
def __init__(self):
#I'm supposed to have the object set to these generic names at first and then after the prompt function they need to be updated.
self.name = 'anonymous'
self.b_year = 'unknown'
def prompt(self):
print('Please enter the following:')
self.name = input('Name: ')
self.b_year = input('Year: ')
b = Book()
b.prompt()
def display(self):
print(f'Author:\n{self.name} (b. {self.b_year})\n')
class Book:
def __init__(self):
self.title = 'untitled'
self.publisher = 'unpublished'
def prompt(self):
self.title = input('Title: ')
self.publisher = input('Publisher: ')
def display(self):
print(f'\n{self.title}\nPublisher:\n{self.publisher}')
p = Person()
`enter code here`p.display()
def main():
p = Person()
b = Book()
b.display()
p.prompt()
b.display() #right here I need it to display the new information
if __name__ == '__main__':
main()
Two things you need to do here. First of all you need to initialize your variables in your Person class. Second of all I don't understand what the point of creating objects in a class and then doing the same outside of the class. I suggest taking the following code and modifying it to your likings. Additionally I reorganized the way you call your methods. First you prompt the user with all the necessary questions, then display them all together.
class Person:
def __init__(self):
self.name = None
self.b_year = None
def prompt(self):
print('Please enter the following:')
self.name = input('Name: ')
self.b_year = input('Year: ')
def display(self):
print(f'Author:\n{self.name} (b. {self.b_year})\n')
class Book:
def __init__(self):
self.title = 'untitled'
self.publisher = 'unpublished'
def prompt(self):
self.title = input('Title: ')
self.publisher = input('Publisher: ')
def display(self):
print(f'\n{self.title}\nPublisher:\n{self.publisher}')
def main():
p = Person()
b = Book()
b.display()
p.display()
p.prompt()
b.prompt()
b.display()
p.display()#right here I need it to display the new information
if __name__ == '__main__':
main()
output
untitled
Publisher:
unpublished
Author:
None (b. None)
Please enter the following:
Name: a
Year: b
Title: c
Publisher: d
c
Publisher:
d
Author:
a (b. b)
I'm not designer so you don't have to go with my idea, but IMO, don't add \n like this '\n{self.title}\nPublisher:\n{self.publisher}'. It looks a bit weird in the output.
You create one Book in the main function, and then another Book inside the Person.prompt method. They aren't the same Book - you have two!
You need to decide if a book belongs within a person, or whether they are two top level objects that may have a relationship. From a "real world" perspective, I don't think a person should automatically have a book associated with them. Perhaps you could create a Book and then pass to the Person constructor...

Python object creating a group with 3 members of aggregation relationship

I had an assignment to create a python code using class to create a group with 3 members (aggregation relationship). This is my code so far:
class Member:
def __init__(self,name,age):
self.name = name
self.age = age
def getInfo(self):
memberInfo = "Name: " + str(self.name) + "." + "Age: " + str(self.age)
return memberInfo
class Group:
def __init__(self,name):
self.name = name
self.memlist = []
def addMember(self,member):
self.memlist.append(member)
def getInfo(self):
info = "Member List: \n"
for i in range(len(self.memlist)):
info += self.memlist[i].getInfo() + "\n"
print(info)
break
mem1 = Member("Chi",20)
mem2 = Member("Bach",7)
mem3 = Member("Gen", 22)
group1 = Group("Siblings")
group1.addMember(mem1)
group1.addMember(mem2)
print(group1.getInfo())
print(mem2.getInfo())
print(group1.memList)
But it has shown an error: AttributeError: 'Group' object has no attribute 'memList'. Is there anything I can do to fix this?
I wrote little function for listing members and their ages.
class member:
def __init__(self, name, age):
self.name = name
self.age = age
def member_Info(self):
memberInfo = f"Name: {str(self.name)}-->Age: {str(self.age)}"
return memberInfo
class Group:
def __init__(self, name):
self.name = name
self.memlist = []
def addMember(self, name):
self.memlist.append(name)
def getInfo(self):
for i in range(len(self.memlist)):
info = self.memlist[i].member_Info() + "\n"
print(info)
This all_members function is basically getting the information stored in the member class and return to list. I print using memlist in Group but it didn't work out so I made a new list using all_member function and get information from memlist in group1 with the code that you used for getting information in memlist at group1.getInfo .
def all_members():
all_mems = []
for i in range(len(group1.memlist)):
all_mems.append(group1.memlist[i].member_Info())
print(all_mems)
mem1 = member("Chi", "20")
mem2 = member("Bach", "7")
mem3 = member("Gen", "22")
group1 = Group("Siblings")
group1.addMember(mem1)
group1.addMember(mem2)
group1.addMember(mem3)
print(group1.getInfo())
print(mem2.member_Info() + "\n")
print(all_members())
I guess this isn't the best answer you can get but I think it will work and also I learn many things while trying to correct it so thank you for posting that.
change
print(group1.memList)
to
print(group1.memlist)

Python: Classes that use other classes

So I have 2 files that work together using each other's classes.
I have
class Student:
"""A class to model a student with name, id and list of test grades"""
def __init__(self, name, id):
"""initializes the name and id number; sets list of grades to []"""
self.s_name = name
self.ident = id
self.tests=[]
def getID(self):
return self.ident
def get_name(self):
""" returns the student name"""
return self.s_name
def addtest(self,t):
"""adds a grade to the list of test grades """
self.tests.append(t)
def __str__(self):
"""returns the student name and the current list of grades"""
return self.s_name + " " + str(self.tests) + " "
def comp_av(self):
"""returns the average of the current set of grades or 'no grades'
if appropriate"""
if len(self.tests) > 0:
sum = 0.0
for item in self.tests:
sum = sum + item
average = float(sum)/len(self.tests)
return average
else:
return "no grades"
Which is completely done. I also have code that is from the teacher's point of view. The students are not just represented by their names but by an object of class Student. Each Student object has their name and ID number, but also a list of test scores. Right now Course has only the constructor and the __str__ method.
from LabStudentClass import *
class Course:
""" A class to model a course which contains a list of students"""
def __init__(self,teacher):
"""Sets up a class to hold and update students"""
self.students = []
self.teacher = teacher
def __str__(self):
""" prints the course by listing each student in the class"""
result = self.teacher+"'s Class\n"
for s in self.students:
name = s.get_name()
result = result + name + '\n'
return result
c = Course("Dr. Bradshaw")
#print c
def AddStudent(name, id):
student1 = Student('Mary Comtpon', '3456')
student2 = Student('Billy Jo', '2345')
student3 = Student( 'Anne lou', '1090')
print student1
print student2
print student3
My goal is to create a method AddStudent: This method gets two parameters, a student name and an ID. A new Student object is created and added to the course.
Add 3 students to your class and print out the class to test it.
However, the students aren't printing and I'm not really sure what the problem is.
Add this method to your Course class:
def addStudent(self, name, id):
student = new Student(name, id)
self.students.append(student)
Then, replace the function you wrote at the bottom with the following:
c.addStudent('Mary Comtpon', '3456')
c.addStudent('Billy Jo', '2345')
c.addStudent('Anne lou', '1090')
print c

Categories