Unbound Error Python Class - python

I have researched everywhere and although I find the same concepts, I cannot seem to find an answer to my error.
I did not post before because my account info was forgotten on stack, but I have grown very frustrated with this beginner's error.
class Person(object):
def __init__(self, name, phone):
self.name = name
self.phone = phone
class Employee(Person):
total_salary = 0
#staticmethod
def total_salary(self, salary):
return total_salary
def __init__(self, name, phone, salary):
self.name = name
self.phone = phone
self.salary = salary
class Student(Person):
def __init__(self, name, phone, gpa):
self.gpa = gpa
self.name = name
self.phone = phone
def __str__(self):
reply = ""
reply = "Person " + self.name + " has phone " + self.phone + "\n" + " and is a Student with gpa " + str(self.gpa)
return reply
class Professor(Employee):
def __init__(self, name, phone, salary, clas_teach):
self.clas_teach = clas_teach
self.name = name
self.phone = phone
self.salary = salary
def __str__(self):
reply = ""
reply = "Person " + self.name + " has phone " + self.phone + "\n" + " and is an Employee with salary " + str(self.salary) + "\n"
reply += " and is a Professor assigned to class " + self.clas_teach
return reply
class Staff(Employee):
def __init__(self, name, phone, salary, position):
self.position = position
self.name = name
self.phone = phone
self.salary = salary
def __str__(self):
reply = ""
reply = "Person " + self.name + " has phone " + self.phone + "\n" + " and is an Employee with salary " + str(self.salary) + "\n"
reply += " and is Staff with title " + self.position
return reply
# Create a list of people
People = [ Student("Sandy", "326-8324", 3.65), Student("Jordan", "632-7434", 3.1), \
Professor("Leslie", "985-2363", 50000.00, "Info 501"), \
Staff("Alex", "743-4638", 25000.00, "Editor") ]
# display information about our people
print "These are the people in the university:"
for person in People:
print person
# display the total salaries of all our employees and average GPA
# of all of our students
print
print "Our total university payroll budget is: " + str(Employee.total_salary)
print "Our average student GPA is: " + str(Student.mean_gpa())

Your main misunderstanding is how classes work. In your code, you are calling classes rather than instances of classes:
print "Our total university payroll budget is: " + str(Employee.total_salary)
print "Our average student GPA is: " + str(Student.mean_gpa())
The key thing here is:
Employee.total_salary
Instead you should be doing something like this:
leslie = Professor("Leslie", "985-2363", 50000.00, "Info 501")
print "Leslie's Salary: " + str(leslie.salary)
For this specific case, you want the total payroll, which is the sum of all employee salaries. You need a collection of employees somewhere.
def University():
def __init__(self):
self.employees[]
def add_employee(self, employee):
self.employees.append(employee)
def get_total_payroll(self):
total = 0
for employee in self.employees:
total += employee.salary
return total
then use an instance of that class:
university = University()
university.add_employee(Professor("Leslie", "985-2363", 50000.00, "Info 501"))
university.add_employee(Staff("Alex", "743-4638", 25000.00, "Editor"))
print "Total payroll: " + str(university.get_total_payroll())
Obviously, there are a lot more adjustments you need to make, like sorting betweeen employees and students, etc. But hopefully this is enough to get you started.

There are problems with your overall design that have been covered in other answers, so I will just try to explain why your current code is not working:
You have created a class attribute named total_salary, and then shadowed it with a method of the same name.
You are using a static method, when you need to use a class method.
You need to call total_salary as a method in order to return its value.
These problems can be fixed like this:
class Employee(Person):
_total_salary = 0
#classmethod
def total_salary(cls):
return cls._total_salary
...
print "Our total university payroll budget is: " + str(Employee.total_salary())
But note that the code will still raise an AttributeError, because you are trying to call Student.mean_gpa, which hasn't been defined yet.

Your class Employee has an attribute AND a method with the same name. Calling Employee.total_salary will return the function because in the MRO it's replacing the attribute.
Change:
class Employee(Person):
total_salary = 0
to
class Employee(Person):
total_salary_value = 0
Your staticmethod total_salary in Employee is returning a variable that doesn't exist(because it's looking only in the method scope), you should return the Employee.total_salary_value. Like so:
#staticmethod
def total_salary():
return Employee.total_salary_value
In the __init__ of Employee you are not instantiating the Person that you are inheriting (the same thing in Student(inheriting Person), Professor and Staff(both inheriting Employee)
Use either:
Person.__init__(self,name,phone)
or
super(Employee, self).__init__(name, phone)
Still in the init, you are not adding the salary to the total_salary_value
add this:
Employee.total_salary_value += self.salary
Also, there's no need to use self.name and self.phone in the Student, because Person already has this attribute. (The same for that and other variables in Professor and Staff)
And lastly, Student doesn't have a method called mean_gpa. You have to implement it.
Here's the code:
class Person(object):
def __init__(self, name, phone):
self.name = name
self.phone = phone
class Employee(Person):
total_salary_value = 0
#classmethod
def total_salary(cls):
return cls.total_salary_value
def __init__(self, name, phone, salary):
Person.__init__(self,name,phone)
self.salary = salary
Employee.total_salary_value += self.salary
class Student(Person):
all_gpa = []
def __init__(self, name, phone, gpa):
Person.__init__(self,name,phone)
self.gpa = gpa
Student.all_gpa.append(self.gpa)
def __str__(self):
return "Person {0} has phone {1} and is a Student with gpa {2}".format(self.name,self.phone,self.gpa)
#classmethod
def mean_gpa(cls):
return sum(cls.all_gpa)/len(cls.all_gpa)
class Professor(Employee):
def __init__(self, name, phone, salary, clas_teach):
Employee.__init__(self,name,phone,salary)
self.clas_teach = clas_teach
def __str__(self):
return "Person {0} has phone {1} and is an Employee with salary {2}\n" \
"and is a Professor assigned to class {3}".format(self.name,self.phone,self.salary,self.clas_teach)
class Staff(Employee):
def __init__(self, name, phone, salary, position):
Employee.__init__(self, name, phone, salary)
self.position = position
def __str__(self):
return "Person {0} has phone {1} and is an Employee with salary {2}\n" \
"and is Staff with title {3}".format(self.name, self.phone, self.salary, self.position)
# Create a list of people
People = [ Student("Sandy", "326-8324", 3.65),
Student("Jordan", "632-7434", 3.1),
Professor("Leslie", "985-2363", 50000.00, "Info 501"),
Staff("Alex", "743-4638", 25000.00, "Editor") ]
# display information about our people
print "These are the people in the university:"
for person in People:
print person
# display the total salaries of all our employees and average GPA
# of all of our students
print
print "Our total university payroll budget is: " + str(Employee.total_salary())
print "Our average student GPA is: " + str(Student.mean_gpa())
EDIT:
As #ekhumoro said, it's better to use a #classmethod to return the value.
Another thing, your __str__ could be made more clear using .format()

Related

Outer class attributes not passing to inner class Attributes for python inheritance

I don't really know what I have done wrong here. I get the error "student has no attribute name" when it gets to the output data function. Any ideas are greatly appreciated.
class Person:
def __init__(self):
self.ID=""
self.name=""
self.address=""
self.Phone_number=""
self.email_id=""
self.student=self.Student()
def read_data(person):
person.ID=input("please enter ID:")
person.name=input("Please enter name:")
person.address=input("Enter address:")
person.Phone_number=input("Enter Phone Number:")
class Student:
def __init__(self):
self.class_status=""
self.major=""
def read_data(student):
student.class_status=input("Enter class status:")
student.major=input("Enter student major:")
def output_data(student):
information=(student.name + " " + student.ID + " " + student.address + " " + student.Phone_number + " " + student.class_status + " " + student.major + "\n")
print(information)
studentFile.write(information)
def StudentDetails():
person=Person()
person.read_data()
student=person.student
student.read_data()
student.output_data()
studentDetails()
The attributes of an outer class aren't passed to an inner class. It looks like you're trying to model an inheritance relationship, which you can do by using subclassing rather than nesting classes. For example, you could do something like the following:
class Person:
def __init__(self):
self.ID=""
self.name=""
self.address=""
self.Phone_number=""
self.email_id=""
def read_data(person):
person.ID=input("please enter ID:")
person.name=input("Please enter name:")
person.address=input("Enter address:")
person.Phone_number=input("Enter Phone Number:")
class Student(Person):
def __init__(self):
super().__init__()
self.class_status=""
self.major=""
def read_data(self):
super().read_data()
self.class_status=input("Enter class status:")
self.major=input("Enter student major:")
def output_data(self):
information=(self.name + " " + self.ID + " " + \
self.address + " " + self.Phone_number + " " + \
self.class_status + " " + self.major + "\n")
print(information)
def studentDetails():
student = Student()
student.read_data()
student.output_data()
studentDetails()
If you are absolutely sure that you must use a nested class, then the relationship you're trying to describe doesn't make sense. I could see something like a student ID class being an inner class of Person to store some additional attributes, but I don't think the relationship as currently described makes much sense.

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

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:Understanding inheritance

Am new to Python and was exploring Classes and Object.
I have created a class,defined few function in it. Then I have created another class and was trying to inherit from the first class but got some error.
Error: class CTC(Salary):
NameError: name 'Salary' is not defined
Base Class:
class Salary:
monthly=0.00
name = ""
def __init__(self,name,monthly):
self.name = name
self.monthly = monthly
def display(self):
print("name: ", self.name, "Monthly Salary: ", self.monthly)
Derived Class:
class CTC(Salary):
tax=0.00
ctc=0.00
def __init__(self,name,monthly,tax):
Salary.__init__(self,name,monthly)
self.tax = tax
def calculateCTC(self):
yearly = monthly*12
totalTax= tax *12
ctc = yearly - totalTax
print("Total CTC: ", self.ctc)
obj = CTC("Rishi",28700.00,1295.00)
obj.display(self)
Can anyone explain me the root cause for the error?
I put all code in one file (with minor modifiactions) and it works form me.
class Salary:
def __init__(self, name, monthly):
self.name = name
self.monthly = monthly
def display(self):
print("name: ", self.name, "Monthly Salary: ", self.monthly)
class CTC(Salary):
def __init__(self, name, monthly, tax):
Salary.__init__(self, name, monthly)
self.tax = tax
self.ctc = 0.00 # create with default value
def calculateCTC(self):
yearly = self.monthly*12 # with `self`
totalTax = self.tax*12 # with `self`
self.ctc = yearly - totalTax # with `self`
print("Total CTC: ", self.ctc)
# without indentation
obj = CTC("Rishi", 28700.00, 1295.00)
obj.display() # without `self`
if you need it in separated files
salary.py
class Salary:
def __init__(self, name, monthly):
self.name = name
self.monthly = monthly
def display(self):
print("name: ", self.name, "Monthly Salary: ", self.monthly)
main.py
from salary import Salary
class CTC(Salary):
def __init__(self, name, monthly, tax):
Salary.__init__(self, name, monthly)
self.tax = tax
self.ctc = 0.00
def calculateCTC(self):
yearly = self.monthly*12 # with `self`
totalTax = self.tax*12 # with `self`
self.ctc = yearly - totalTax # with `self`
print("Total CTC: ", self.ctc)
# without indentation
obj = CTC("Rishi", 28700.00, 1295.00)
obj.display() # without `self`
I formated your code and it works for me.
class Salary:
monthly=0.00
name = ""
def __init__(self,name,monthly):
self.name = name
self.monthly = monthly
def display(self):
print("name: ", self.name, "Monthly Salary: ", self.monthly)
class CTC(Salary):
tax=0.00
ctc=0.00
def __init__(self,name,monthly,tax):
Salary.__init__(self,name,monthly)
self.tax = tax
def calculateCTC(self):
yearly = monthly*12
totalTax= tax *12
ctc = yearly - totalTax
print("Total CTC: ", self.ctc)
obj = CTC("Rishi",28700.00,1295.00)
obj.display(self)
Unlike Java, which forces developer to put each class in each file, Python is more flexible. In Python you can write as much code as you want in a single file, meaning that you can have both of your classes in a single file, without needing to import anything. The diffrence is in importing. Java doesn't need you to import any of your project files, Python on the other hand requires you to import anything that is in external packages, no matter where are they kept. So just import your Salary to the file with CTC.

Python Referencing a name of a class object in a function

I've never used classes before and I am trying to get a general understanding of how they work with the code example I have below. Im having issues referencing one of the names i define for a class. i just want the program to print out a list of the employee names and salaries stored in the list when the option 2 is entered but it gives me the following error:
Traceback (most recent call last):
File "C:\Scott Glenn\Misc\classes.py", line 31, in
employees[i].displayEmployee
AttributeError: 'str' object has no attribute 'displayEmployee'
class Employee:
'Common base class for all employees'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print "Total Employee %d" % Employee.empCount
def displayEmployee(self):
print "Name : ", self.name, ", Salary: ", self.salary
def AddNewEmployee():
NewEmployee = raw_input("What is the Employees name: ")
employees.append(str(NewEmployee))
NewEmployeeSalary = raw_input("What is the Employees salary: ")
NewEmployee = Employee(NewEmployee, NewEmployeeSalary)
return employees
#=============================================================================
employees=[]
while(1):
print'Welcome to the Employee Database!'
option = raw_input('Please select 1 to add new employee or 2 to display all current employees: ')
if option=='1':
employees.append(AddNewEmployee())
if option=='2':
for i in range(0,len(employees)):
employees[i].displayEmployee
The AddNewEmployee function is wrong. It's returning a list of a single string when you want to be returning a single object of your custom type Employee.
It should be more like this:
def AddNewEmployee():
#string variable to hold name
NewEmployeeName = raw_input("What is the Employees name: ")
#why make a list? you are appending the result of this function to that list
#employees.append(str(NewEmployee))
#plus this is adding the employee before he's even been created
NewEmployeeSalary = raw_input("What is the Employees salary: ")
#construct using name string and salary string
NewEmployee = Employee(NewEmployeeName, NewEmployeeSalary)
return NewEmployee #return Employee object (to be appended later)
Additionally, you are trying to access displayEmployee() as a field of your class, instead of as a method. Fields don't have parenthesis and methods do (so they can take parameters, though in this case the parenthesis are empty as no parameters are passed).
Finally, note that raw_input returns a string so you should cast to float if that is what you wish your NewEmployeeSalary to be. (Right now it's a string.)
I've updated your code below. The main issue that I saw that you had was that you were using 'employees' as a global and appending to it twice. I moved it out of the AddNewEmployee() function and had that return the new employee which is then appended to 'employees'
Also you weren't calling '.displayEmployees'
Notice the the parentheses that I added to the end.
I hope this helps!
class Employee(object):
'Common base class for all employees'
empCount = 0
def __init__(self, name, salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print "Total Employee %d" % Employee.empCount
def displayEmployee(self):
print "Name : ", self.name, ", Salary: ", self.salary
def AddNewEmployee():
NewEmployee = raw_input("What is the Employees name: ")
NewEmployeeSalary = raw_input("What is the Employees salary: ")
NewEmployee = Employee(NewEmployee, NewEmployeeSalary)
return NewEmployee
# =============================================================================
if __name__ == "__main__":
employees = []
while True:
print'Welcome to the Employee Database!'
option = raw_input(
'Please select 1 to add new employee or 2 to display all current employees: ')
if option == '1':
employees.append(AddNewEmployee())
if option == '2':
for i in range(0, len(employees)):
employees[i].displayEmployee()

Categories