Creating instances of a class using for loop - python

I have created a class that takes name,id number and salary for each object. inside the class there are functions for adding or deduction of the salary and showing the status for each employee:
class emp():
def __init__(self,name,id_num,salary):
self.name=name
self.id=id_num
self.s=salary
def bounus(self,bon):
self.s+=bon
print(" the empolyee %s got a raise of %s"%(self.name,bon))
def ded(self,d):
self.s-=d
print(" the empolyee %s got a deduction of %s"%(self.name,d))
def show(self):
s="the employee {} with id number {} has a salary of {}".format(self.name,self.id,self.s)
print(s)
so I wanted to create a number of objects of my chioce using "range" function in the "for" loop as the following:
for i in range(1,3) :
o=str(input("Enter the employees number %s name\n"%i))
p=input("Enter his\her id number\n")
q=input("Enter his\her salary\n")
ai=emp(o,p,q)
ai.show()
in that way, it loops through 1 and 2 creating objects a1 and a2 and it worked but when I try to show them outside the loop as the following:
a1.show()
it says,a1 is undefined although I could show them inside the loop , how can I store the objects so I can show or apply functions on them after looping .thanks

The i in ai does not get processed as a seperated variable, it just becomes one whole ai.
Instead, you should make a list a, which you can access with a[i].
a = []
for i in range(2) : # Slight change to start at i=0
o=str(input("Enter the employees number %s name\n"%i))
p=input("Enter his\her id number\n")
q=input("Enter his\her salary\n")
a.append(emp(o,p,q))
a[i].show()

Selcuk identified your issue, but here is a code snippet based on your code that may help you conceptualize his advice:
new_employees = []
for i in range(1,3):
name = input("Enter the employees number %s name\n" %i)
id_num = input("Enter his\her id number\n")
salary = input("Enter his\her salary\n")
employee = emp(name, id_num, salary)
employee.show()
new_employees.append(employee)
At the end of the loop you will now have a list of new employees that you can do other things with. So, per your comment assume you want to deduct $25 from the salary of on the employee with the employee id of 5. You could something like this if you didn't want to get fancy:
target_employee = None
for employee in new_employees:
if employee.id == 5:
target_employee = employee
break
if target_employee:
target_employee.ded(25)

Here is another way that auto-creates a name for each employee the way you intended and stores that name and the employee object in a dictionary. Each employee can then be called by his name from outside the loop with full access to all the class methods. Also class names should always be capitalized. Object names are in lower case:
class Emp():
def __init__(self, name, id_num, salary):
self.name = name
self.id = id_num
self.s = salary
def bonus(self, bon):
self.s += bon
print("The empolyee %s got a raise of %s" % (self.name, bon))
def ded(self, d):
self.s -= d
print("The empolyee %s got a deduction of %s" % (self.name, d))
def show(self):
s = "The employee {} with id number {} has a salary of {}".format(self.name, self.id, self.s)
print(s)
employees = {}
for i in range(1, 3):
o = input("Enter the employees number %s name\n" % i)
p = input("Enter his\her id number\n")
q = int(input("Enter his\her salary\n"))
emp = Emp(o, p, q)
name = "a" + str(i)
employees[name] = emp
employees["a1"].show()
employees["a2"].bonus(500)
employees["a2"].ded(200)
employees["a2"].show()

The first mistake you have done is declaring the class inside the for loop. The scope of the object is limited to the for loop and will be destroyed after the loop and moreover you cannot store all the values wrt to the loop as every time a loop is run the new object will be invoked destroying all the previous one hence us the list to append them and try

Related

AttributeError: "type object 'Employee' has no attribute 'Worker'"

Taking a class on Python coding and trying to use inheritance to code an answer to this problem: Write an Employee class that keeps data attributes for the following piece of information:
Employee name
Employee ID
Employee phone #
Next, write a class named ProductionWorker class should keep data attributes for the following information:
Shift number (an integer, such as 1, 2, 3)
Room (bakery, topping, Quality control)
Hourly pay rate
The workday is divided into two shifts: day and night. The shift attribute will hold an integer value representing the shift that the employee works. The day shift 1 and the night shift is shift 2. Write the appropriate accessors and mutator methods for each class.
Once you have written the classes, write a program that creates an object of the ProductionWorker class which prompts the user to enter data for each of the object's data attributes. Store the data in the object, then use the object's accessor methods to retrieve it and display it to the screen.
Why am I getting the error I described in the title?
My Code:
class Employee(object):#Creates Superclass Employee
def __init__(self,name,EmplId,EmpPhone):#Creates Employee class with several parameters
self.name = name#Initial Attribute for Employee Name
self.EmplId = EmplId#Initial Attribute for Employee ID #
self.EmpPhone = EmpPhone#Initial attribute for Employee Phone #
class Worker(Employee):#Creates Subclass of Employee called Worker
def __init__(self,name,EmplId,ShiftNum,EmpPhone,PayRate):#Set initial state of Worker Subclass
Employee.__init__(self,name,EmplId,EmpPhone)
self.ShiftNum = ShiftNum#Initial Shift number value for class Worker
self.PayRate = PayRate#Initial Payrate for class Worker
def main():#Creates Main method
WorkerName = " "
WorkerIDNum = " "
WorkerShiftNum = 0
WorkerPayRate = 0.0
WorkerPhoneNum = " "
#Getting data attributes to passed into Employee and Worker classes
WorkerName = input("Enter the Workers name: ")
WorkerIDNum = ("Enter the Workers Id Number: ")
WorkerShiftNum = input ("Enter the Workers shift number (1,2,or 3): ")
WorkerPayRate = input ("Enter the works payrate in dollars an cents: ")
WorkerPhoneNum = input ("Enter the employees 9 Digit phone number:")
worker = Employee.Worker(WorkerName,WorkerIDNum,WorkerShiftNum,WorkerPhoneNum,WorkerPayRate)
#Above line creates an Instance of the Employee superclass and Worker subclass called "worker"
#Values the user entered are pass in as attributes to the object.
#Printing User entered information
print("Worker information entered: ")
print("Name: ", worker.name)
print("EMployee ID Number: ", worker.EmplId)
print("Employee Shift Number: ", worker.ShiftNum)
print("Worker Hourly Payrate: $", worker.PayRate)
main()```
The solution to your problem was provided in the comments... you must instantiate only the subclass (ie. Worker, not Employee.Worker), but I see more problems. My example below illustrates one way to fix them. You are creating a lot of arbitrary values, and not performing any checks or limits on them. Everything comes from outside of your class and needs to be clumsily injected into the __init__ arguments. Then to print the Worker you gather all of the data externally and format it into print statements. Why not make your classes smart enough to handle all of this internally?
To put this another way. You are basically just grabbing a bunch of junk, throwing it in a class constructor and calling it a Worker. You should be able to just call Worker and it handles getting, formatting and limiting everything that it expects.
Below we store all the final values in private variables. We tie all assignments to "setters" and trigger those "setters" in __init__. This allows us to force variables to satisfy certain conditions before we accept them. It also allows us to change properties of the Worker (after instantiation) while following the exact same system.
#Creates Superclass Employee
class Employee(object):
#property
def name(self) -> str:
return self.__name
#name.setter
def name(self, name:str) -> None:
while not name:
name = input("Enter The Worker's Name: ")
self.__name = name
#property
def phone(self) -> str:
return self.__phone
#phone.setter
def phone(self, phone) -> None:
phone = f'{phone}'
#get and check phone
while not phone.isdigit() or len(phone) != 10:
phone = input("Enter The Worker's 10 digit Phone Number: ")
#store phone
self.__phone = phone
#property
def eid(self) -> int:
return self.__eid
#eid.setter
def eid(self, eid) -> None:
if not isinstance(eid, int):
eid = f'{eid}'
#get and check employee id
while not eid.isdigit():
eid = input("Enter The Worker's ID Number: ")
eid = int(eid)
#store id
self.__eid = eid
def __init__(self):
self.name, self.phone, self.eid = '', '', ''
#Creates Subclass of Employee called Worker
class Worker(Employee):
#property
def shift(self) -> int:
return self.__shift
#shift.setter
def shift(self, shift) -> None:
if not isinstance(shift, int) or (isinstance(shift, int) and shift not in (1, 2, 3)):
shift = f'{shift}'
#get and check shift number
while not shift.isdigit() or not shift in ('1', '2', '3'):
shift = input("Enter The Worker's Shift Number (1, 2, 3): ")
shift = int(shift)
#store shift
self.__shift = shift
#property
def rate(self) -> float:
return self.__rate
#rate.setter
def rate(self, rate) -> None:
if not isinstance(rate, (float, int)):
rate = f'{rate}'
#get and check pay rate
while True:
try:
float(rate)
break
except ValueError:
pass
rate = input("Enter The Worker's Pay Rate in Dollars and Cents: ")
rate = float(rate)
#store rate
self.__rate = rate
def __init__(self):
Employee.__init__(self)
self.shift, self.rate = '', ''
#for printing the worker props
def __str__(self):
return f'Worker Information:\n\tname: {self.name}\n\tid: {self.eid}\n\tphone: {self.phone}\n\tshift: {self.shift}\n\trate: {self.rate}'
#this is so much cleaner. Make a Worker and print the instance.
if __name__ == "__main__":
worker = Worker()
print(worker)

Python, program open and close in 10th of second

Here is my code as follows.
# starting of Employee class
class Employee(object):
def __init__(self): #declaring Constructor
self.name = ""
self.iDnumber = ""
self.department = ""
self.jobTitle = ""
# setter methode for setting values to the class properties
def setName(self,name):
self.name=name
def setIDnumber(self,iDnumber):
self.iDnumber=iDnumber
def setDepartment(self,department):
self.department=department
def setJobTitle(self,jobTitle):
self.jobTitle=jobTitle
# getter methode for getting values of the class properties
def getName(self):
return self.name
def getIDnumber(self):
return self.iDnumber
def getDepartment(self):
return self.department
def getJobTitle(self):
return self.jobTitle
# methode which takes object as an argument and display its properties
def display(emp_object):
print("Name : ",emp_object.getName())
print("IDnumber : ",emp_object.getIDnumber())
print("Department : ",emp_object.getDepartment())
print("JobTitle : ",emp_object.getJobTitle())
# Main methode of the program
if __name__ == "__main__":
employeeList = [] #List to hold the Employee objects
emp1 = Employee()
emp2 = Employee()
emp3 = Employee()
# appending objects to the list
employeeList.append(emp1)
employeeList.append(emp2)
employeeList.append(emp3)
# Initializing each objects of the list
for employee in employeeList:
emp_name = input("Enter your Name ")
employee.setName(emp_name)
emp_iDnumber = input("Enter your iDnumber ")
employee.setIDnumber(emp_iDnumber)
emp_department = input("Enter your Department ")
employee.setDepartment(emp_department)
emp_jobTitle = input("Enter your JobTitle ")
employee.setJobTitle(emp_jobTitle)
# Displaying each objects of the list
for emp_object in employeeList:
display(emp_object)
and, when I run it termianl just flash for a 10th of seconds and do not ask for input.
Help me with this thank you.
I am trying to focus on
Display a message asking user to enter employee name, ID, department, and title
b. Read employee name into a variable
c. Call the set name method of the first object passing the name
d. Read employee ID into a variable
Probably you are running it on windows... Simple add a input() at the end of you main to pause program and prevent windows from close it
And you need to indent your code
if __name__ == "__main__":
employeeList = [] #List to hold the Employee objects
emp1 = Employee()
emp2 = Employee()
emp3 = Employee()
# appending objects to the list
employeeList.append(emp1)
employeeList.append(emp2)
employeeList.append(emp3)
input()

Having a constantly changing variable in a python loop

I'm trying to write a program that would ask for a students name, a couple other numerical values, and assign them to groups, via their numerical value, to have all groups as close to equal as possible (by taking the the highest next value in the list, and assigning it to the next group and so on).
However, I'd need to save their number to some variable, as well as their name, to then print out the group's list.
For this I'd need a variable that changes everytime the loop goes through to add another student. I'd also need to sort these number, and then somehow call back the name they corrispond to after they've been sorted into groups, and I'm not sure how to do any of these. Is there any way for this to be done, would I have to use another language?
This is the code I have so far:
from easygui import *
times = 0
name = 0
s_yn = ynbox("Would you like to enter a student?")
while s_yn == 1:
msg = "Student's Information"
title = "House Sorting Program"
fieldNames = ["Name", "Grade","Athleticism (1-10)","Intellect (1-10)","Adherance to school rules (1-10)"]
fieldValues = []
fieldValues = multenterbox(msg,title, fieldNames)
times = times + 1
ath = fieldValues[2]
int_ = fieldValues[3]
adh = fieldValues[4]
ath = int(ath)
int_ = int(int_)
adh = int(adh)
total = ath+int_+adh
s_yn = ynbox("Would you like to enter a student?")
I believe it would be nice to create a Student class that holds all variables associated with a student. Then you could add each student to a list which you could sort by the values you want and divide to how many groups you want.
from easygui import *
from operator import attrgetter
class Student(object):
def __init__(self, name, grade, athleticism, intellect, adherance):
self.name = name
self.grade = int(grade)
self.athleticism = int(athleticism)
self.intellect = int(intellect)
self.adherance = int(adherance)
self.total = self.athleticism + self.intellect + self.adherance
def __str__(self): # When converting an instance of this class to a string it'll return the string below.
return "Name: %s, Grade: %s, Athleticism (1-10): %s, Intellect (1-10): %s, Adherance to school rules (1-10): %s"\
% (self.name, self.grade, self.athleticism, self.intellect, self.adherance)
student_group = []
while ynbox("Would you like to enter a student?"): # Returns 'True' or 'False' so it'll loop every time the user press 'yes'.
message = "Student's Information"
title = "House Sorting Program"
field_names = ["Name", "Grade", "Athleticism (1-10)", "Intellect (1-10)", "Adherance to school rules (1-10)"]
field_values = multenterbox(message, title, field_names)
student = Student(*field_values) # Unpack all elements in the list 'field_values' to the initializer.
student_group.append(student) # Add the student to the group 'student_group'.
# When the user has put in all the students we sort our group by 'total' (or any other value you want to sort by).
sorted_group = sorted(student_group, key=attrgetter("total"), reverse=True)
# Just as an example I divided the students into 3 groups based on their total.
best_students = sorted_group[:len(sorted_group) // 3]
average_students = sorted_group[len(sorted_group) // 3:2 * len(sorted_group) // 3]
worst_students = sorted_group[2 * len(sorted_group) // 3::]

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

Python Dynamic Object Creation [duplicate]

This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 8 years ago.
I have tried using list and/or dictionaries to store the objects that I create, but my attempts have failed.
A reasons to use a list or a dictionary is to have python keep a reference to the object so as prevent the garbage collection component from discarding our object. My issues seems to be more with the initialization of the object itself, and with naming the object.
My script takes data out of a database and then automatically creates objects for each item in the list, in our case, employees.
Here is my class:
class Employee:
empCount = 0
def __init__(self, employee_id, name, age):
self.employee_id = employee_id
self.name = name
self.age = age
Employee.empCount += 1
def display_employee_count(self):
print("Total Employee %d" % Employee.empCount)
def display_employee(self):
print("Employee ID : ", self.employee_id,
" First name : ", self.name,
' Age : ', self.age)
I know that to create an object I would call
joe1883 = Employee('joe1883', 'Joe', 21)
To display the objects attributes I would
joe1883.display_employee()
which yields:
Employee ID : joe1883 First name : Joe Age : 21
My question is, how do I do this through a loop ?
# Data set has, employee id, first name, and age
my_list = [['joe1883', 'joe', 21],
['bob1492', 'bob', 22],
['frank1889','frank',34]]
for names in my_list:
employee_id = names[0]
name = names[1]
age = names[2]
#print("Employee ID : " + employee_id + " First name : " + name + ' Age : ' + str(age))
# This is the line that creates my error !
employee_id = Employee(employee_id, name, age)
If I insert this line into the loop statement
employee_id = Employee(employee_id, name, age)
And then call
joe1883 = Employee('joe1883', 'Joe', 21)
I get a #NameError: name 'joe1883' is not defined.
You need to keep a reference to an object around not just so it isn't garbage-collect, but also so you can reference it. The reference can be by giving it a variable name, like joe1883, or it can be by storing the object in a container, like a list or dictionary.
If you put it in a list, each element in the list can be reference with an integer index, such as employees[42]. To find an employee in such a container you will need to search through potentially all of them, by index, until you find the one you want.
If you want to find an employee quickly given their id, you should store them in a dictionary instead, then you could do something like employees['joe1883'] to directly access one of them.
Since you don't know kind of container an Employee instance will be put in, if any, it makes little sense to keep an empCount in the class. If you put a bunch of them in a list or dictionary, and ever need to know how many, you can find that by using the built-in len() function on the container object, i.e. len(employee_list) or len(employee_dict).
class Employee:
def __init__(self, id, name, age):
self.id = id
self.name = name
self.age = age
def display(self):
print("Employee ID : ", self.id,
" First name : ", self.name,
' Age : ', self.age)
# create a single employee object and name it joe1883
joe1883 = Employee('joe1883', 'Joe', 21)
joe1883.display()
# now create a list of employees by converting dataset
# my_list into a list of Employee instances named employees
# dataset
my_list = [
['joe1883', 'joe', 21],
['bob1492', 'bob', 22],
['frank1889','frank', 34],
]
employees = [Employee(item[0], item[1], item[2]) for item in my_list]
# display each employee in list
for employee in employees:
employee.display()
# or you could do it this (non-pythonic) way:
for i in range(len(employees)):
employees[i].display()
# to print an employee with a given id
# you'd need to search for it in the list
for employee in employees:
if employee.id == 'joe1883':
employee.display()
break # found, so stop loop
# Here's how to create a dictionary of employees by converting dataset
# my_list into Employee instances keyed by their id
employees = {item[0]: Employee(item[0], item[1], item[2]) for item in my_list}
# look one of them up
if 'joe1883' in employees:
employees['joe1883'].display()
If I understand your question correctly, you are trying to create a set of objects-employees based on the list with the arguments for each of the objects.
I modified/simplified your code a little bit and this is working fine:
class Employee:
empCount = 0
def __init__(self, employee_id, name, age):
self.employee_id = employee_id
self.name = name
self.age = age
Employee.empCount += 1
def display_employee_count(self):
print("Total Employee %d" % Employee.empCount)
def display_employee(self):
print("Employee ID : {0} First name : {1} Age : {2}".format(self.employee_id, self.name,self.age))
my_list = [('joe1883', 'joe', 21), ('bob1492', 'bob', 22), ('frank1889', 'frank', 34)] # in this format arguments will be easier to pass as parameters to your class constructor
list_of_employees = [] # list where you can put created objects
for emp in my_list:
list_of_employees.append(Employee(*emp)) # now you just pass your tuple of arguments like that
for emp in list_of_employees: #looping through the list with objects you created and printing results
emp.display_employee()
#eduard You are doing 2 things wrong.
1) the indentation is bad, so the methods of the class Employee are not inside the class.
2) You are not storing the objects anywhere.
Id suggest you to do it in this way:
employ_dic={}
class Employee:
def __init__(self, employee_id, name, age):
self.employee_id = employee_id
self.name = name
self.age = age
employ_dic[employee_id]=self
def display_employee(self):
print '''Employee ID: {0}, First Name: {1}, Age: {2}'''.format(self.employee_id, self.name, self.age)
lists = [['joe1883', 'joe', 21],['bob1492', 'bob', 22],['frank1889','frank',34]]
for list in lists:
employee_id = Employee(list[0], list[1], list[2])
employ_dic['joe1883'].display_employee()
# to display the count:
print len(employ_dic)

Categories