Modifying parent class attribute from child class method - python

I have two classes, one parent called Organization and one child called Employee. Organization has an attribute called org_size which I want to be able to increment when I call my add_employee method that belongs to the Employee class.
class Organization( object ):
def __init__(self, org_name):
self.org_name = org_name
self.org_size = 0
self.org_revenue = 0
self.num_placements = 0
def get_org_size(self):
return self.org_size
class Employee( Organization ):
def __init__(self, employee_name, comission_rate):
self.employee_name = employee_name
self.comission_rate = comission_rate
self.total_comission = 0
def add_employee(employee_name, comission_rate):
employee = Employee(employee_name, comission_rate)
self.org_size += 1
return employee
team = Organization("My Sales Team")
emp = Employee("Bob", 15)
Regardless if I call team.org_size or team.get_org_size(), I get an answer of 0, instead of the expected 1, as I want to increment org_size as part of calling the add_employee() method. I tried adding a super() to Employee but then whenever I called add_employee it caused issues with requiring the org_name argument from Organization.
What do I need to do with Employee class in order to modify attributes in Organization?

The relationship between Organization and Employee is a "HAS A" relationship, not an "IS A" relationship. An Employee is not a KIND OF an organization, she is a MEMBER of an organization.
class Organization():
def __init__(self, org_name):
self.org_name = org_name
self.org_size = 0
self.org_revenue = 0
self.num_placements = 0
self.employees = []
def add_employee(self, employee_name, comission_rate):
employee = Employee(employee_name, comission_rate)
self.employees.append(employee)
return employee
def get_org_size(self):
return len(self.employees)
class Employee():
def __init__(self, employee_name, comission_rate):
self.employee_name = employee_name
self.comission_rate = comission_rate
self.total_comission = 0
team = Organization("My Sales Team")
bob = team.add_employee("Bob", 15)

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.

How to make each instance of a child class not require parent attributes (kinda?)

class User:
def __init__(self, username):
self.username = username
#classmethod
def get_user(cls):
return cls(input("Username: "))
class Budget(User):
def __init__(self, monthtly_income):
super().__init__(User.get_user())
self.monthly_income = monthtly_income
self.perc_lis = []
self.category_obj_lis = []
self.category_name_lis = []
self.value_lis = []
...
# creates objects and adds them to a list
for i in range(len(self.category_name_lis)):
self.category_obj_lis.append("")
self.category_obj_lis[i] = Category(self.category_name_lis[i], self.monthly_income)
...
class Category(Budget):
def __init__(self, name, monthly_income):
super().__init__(monthly_income)
self.name = name
self.perc = 0
self.amt = 0
self.left = 0
self.max = 0
# defines the percentage for each category
def get_perc(self):
self.perc = float(input(f"{self.name}: "))
When I run this it asks for username 3 times after I have asked for the categories because I create each Category object in a loop. Username is asked for at the start of the code. I need the category class to be a child class because I need the monthly_income variable to use in code not posted. I am not very good at inheritance so i could easily be missing something obvious. Is there a way for each instance of Category to not ask for username and just use the one already asked in the beginning? I apologize if this is somewhat confusing but idk where to go from here.

How to store my created objects into a array in Python

so im new to programming, so for anything hahahahahah.
So im trying to create a simple manegment system by creating a person registration and a room registration, and simply place the amount of people registerd into the amount of room.
Só this is what im up-to:
class Person:
counter = 0
persons = []
def __init__ (self,name,surname):
self.name = name
self.surname = surname
self.id = Person.counter
Person.counter += 1
def createPeople(self):
print(self.name, self.surname)
def peopleCounter (self):
print(Person.counter)
def storePeople ():
a = Person.createPeople.append(Person.persons)
print(a)
person1 = Person("Jack", "Wayne")
person1.createPeople()
person2 = Person("Gabriel", "Jones")
person2.createPeople()
print(Person.counter)
print(storePeople)
If what you are trying to do is store all persons created in the class attribute persons, then this is how you can go about it:
class Person:
counter = 0
persons = []
def __init__ (self,name,surname):
self.name = name
self.surname = surname
self.id = Person.counter
Person.counter += 1
def createPeople(self):
print(self.name, self.surname)
Person.persons.append(self.name + ' '+ self.surname) #Every time this method is called, it adds the person to the persons list
def peopleCounter (self):
print(Person.counter)
person1 = Person("Jack", "Wayne")
person1.createPeople()
person2 = Person("Gabriel", "Jones")
person2.createPeople()
print(Person.counter)
print(Person.persons)
Output from my end
Jack Wayne
Gabriel Jones
2
['Jack Wayne', 'Gabriel Jones']

Understanding Inheritance

I'm trying to understand inheritance better. In the following code, when I try to print friend.salary, it throws an AttributeError. Doesn't WorkingStudent inherit all methods of the Student class?
class Student:
def __init__(self,name,school):
self.name = name
self.school = school
self.marks = []
def average(self):
return sum(self.marks)/len(self.marks)
def friend(self,friend_name):
return Student(friend_name, self.school)
anna = Student("Anna","MIT")
friend = anna.friend("Motilal")
#print (friend.name)
#print (friend.school)
class WorkingStudent(Student):
def __init__(self,name,school,salary):
super().__init__(self,name,school)
self.salary = salary
anna = WorkingStudent("Anna","SXS",25000)
anna.friend("Greg")
anna.marks.append(50)
print friend.salary
You should modify your source code as below
class Student:
def __init__(self,name,school):
self.name = name
self.school = school
self.marks = []
def average(self):
return sum(self.marks)/len(self.marks)
def friend(self,friend_name):
return Student(friend_name, self.school)
anna = Student("Anna","MIT")
friend = anna.friend("Motilal")
#print (friend.name)
#print (friend.school)
class WorkingStudent(Student):
def __init__(self,name,school,salary):
super(WorkingStudent,self).__init__(name,school)
self.salary = salary
# anna = WorkingStudent("Anna","SXS",25000)
def friend(self,friend_name):
return WorkingStudent(friend_name, self.school, self.salary)
# You should put your code here, because as your original code
# anna is an instance of Student not WorkingStudent class
# so it and its friend don't have "salary".
anna = WorkingStudent("Anna","SXS",25000) # After this line, anna is a different variable to "anna" variable that was defined before (anna = Student("Anna","MIT"))
friend = anna.friend("Greg") # friend now is an instance of WorkingStudent class, so it have salary
anna.marks.append(50)
print(friend.salary)
Editted. So code can work now

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