Initializing subclass variable in Python - python

Here I have a sample code to test python class inheritence.
Here , the base class is ‘Person’ and the ‘Employee’ inherits the base class -‘Person’. Also, there are 2 more subclasses inhertis class ‘Employee’.
I would like to initialize subclass veriables in sub classes - ‘OfficeWorker’ and ‘ProductionWorker’, but I am getting ‘TypeError: __init__() takes 2 positional arguments but 7 were given’.
Need pyhton experts suggestion here to define and initialize subclass variable and correct my code
<snip of error>
#$ ./employee86253.py
Enter the name: sunnily
Enter the address: 41801
Enter the phone: 345
Enter the ID number: 12
Enter the employee type ('S' for salaried or 'H' for hourly): S
Enter the skill type ('eng', 'acc', 'sales', 'mgr'): eng
Enter the monthly salary: 123
Traceback (most recent call last):
File "./employee86253.py", line 110, in <module>
main ()
File "./employee86253.py", line 78, in main
**ERROR:**
**worker = OfficeWorker(worker_name, worker_address, worker_phone, worker_id, skill_type, salary)
TypeError: __init__() takes 2 positional arguments but 7 were given**
================== script =======================
#!/usr/bin/env python
# Base class
class Person:
def __init__ (self, name, address, phone_number):
self.name = name
self.address = address
self.phone_number = phone_number
def get_name(self):
return self.name
def get_address(self):
return self.adress
# subclass, inheriting class - Person
**class Employee (Person):
def __init__(self, id_number):
Person.__init__(self, name, address, phone_number)
self.id_number = id_number**
def get_id_number(self):
return self.id_number
# sub class, inheriting Class - Employee
class ProductionWorker (Employee):
**def __init__(self, shift_number, pay_rate):
super().__init__(id_number)
self.shift_number = shift_number
self.pay_rate = pay_rate**
def get_shift_number ( self ):
return self.shift_number
def compute_pay_for_hours( self, hours):
minutes = hours * 60
return ( minutes * self.pay_rate ) / minutes
def get_pay_rate(self ):
return self.pay_rate
# Subclass, inheriting class - Employee
class OfficeWorker (Employee):
**def __init__(self, skill_type, monthly_salary):
super().__init__(id_number)
self.skill_type = skill_type
self.monthly_salary = monthly_salary**
def get_skill_type(self):
return self.skill_type
def compute_pay_for_weeks(self, weeks):
return (weeks * self.monthly_salary ) / 4
def get_month_salary( self ):
return self.monthly_salary
def main():
# Local variables
worker_name= ''
worker_id = ''
worker_shift = 0
worker_pay = 0.0
skill_type = ''
salary = 0.0
emp_type = 'P'
**# Get data attributes
worker_name = input('Enter the name: ')
worker_address = input('Enter the address: ')
worker_phone = input('Enter the phone: ')
worker_id = input('Enter the ID number: ')
emp_type = input('Enter the employee type (\'S\' for salaried or \'H\' for hourly): ')
if emp_type == 'S':
skill_type = input('Enter the skill type (\'eng\', \'acc\', \'sales\', \'mgr\'): ')
salary = float(input('Enter the monthly salary: '))
worker = OfficeWorker(worker_name, worker_address, worker_phone, worker_id, skill_type, salary)
elif emp_type == 'H':
worker_shift = int(input('Enter the shift number: '))
worker_pay = float(input('Enter the hourly pay rate: '))
worker = ProductionWorker(worker_name, worker_address, worker_phone, worker_id, worker_shift, worker_pay)
else:
print('Invalid employee type')
return**
# Create an instance of ProductionWorker
# Display information
print ('Employee information:')
print ('Name:', worker.get_name())
print ('Address:', worker.get_address())
print ('Phone:', worker.get_phone())
print ('ID number:', worker.get_id_number())
if isinstance(worker,ProductionWorker):
print ('Shift:', worker.get_shift_number())
print ('Hourly Pay Rate: $', \
format(worker.get_pay_rate(), ',.2f'), sep='')
print ('Pay Amount for 5.2 hours: $', \
format(worker.compute_pay_for_hours(5.2), ',.2f'), sep='')
else:
print ('Skill type:', worker.get_skill_type())
print ('Monthly Salary: $', \
format(worker.get_month_salary(), ',.2f'), sep='')
print ('Pay Amount for 2.5 months: $', \
format(worker.compute_pay_for_weeks(10), ',.2f'), sep='')
# call the main function
main ()

Taking the simplest case as an example (but you've got clones of this all over the place):
def __init__(self, id_number):
Person.__init__(self, name, address, phone_number)
where do you think name, address, phone_number will come from? If they're supposed to be arguments to the call to Employee then they must be listed as arguments to its __init__ (and "passed up to it" from further subclasses as needed).

Related

AttributeError: class object has no attribute

I am new to python. I try to access the attribute acnt_amount from the class bank_Customer, but throws "AttributeError" error. How to access the attribute of the function getDetails to withdraw with in the class from one function to another function? What is the mistake that i do? Any help will be much appreciated! Thanks in advance!
Code:
class bank_Customer:
def getDetails(self, cname, acnt_no, acnt_type, acnt_amount):
self.cname = cname
self.acnt_no = acnt_no
self.acnt_type = acnt_type
self.acnt_amount = acnt_amount
row = self.cname + "," + str(self.acnt_no) + "," + self.acnt_type + "," + str(self.acnt_amount) + "\n"
file = open('cust_details.csv','a')
file.write(str(row))
file.close()
print('*'*40)
print("Account has been added successfully!")
return self.acnt_amount
def withdraw(self):
cash = int(input("Please enter the amount to be withdrawn: "))
self.acnt_amount = self.acnt_amount - cash
f"balance amount is {balance}"
return balance
base = bank_Customer()
base.withdraw()
Error:
Traceback (most recent call last):
File "C:\Users\kisha\IdeaProjects\Git projects in python\ATM application.py", line 96, in <module>
base.withdraw()
File "C:\Users\kisha\IdeaProjects\Git projects in python\ATM application.py", line 66, in withdraw
self.acnt_amount = self.acnt_amount - cash
AttributeError: 'bank_Customer' object has no attribute 'acnt_amount'
As suggested, an init is required. Also consider setting up some defaults, and look at the use of "getters and setters".
You may gain some insight from the following sample bank account class that I wrote some time ago as an example.
# #Author:srattigan
# #Date:2020-12-10 11:10:33
# #LastModifiedBy:srattigan
# #Last Modified time:2020-12-14 09:50:13
# demo class for inheritance
class BankAccount:
"""Generic Bank Account
"""
acc_num = 100000
def __init__(self, name, balance=0):
self.name = name
self.balance = balance
self.account_num = self.acc_num
BankAccount.acc_num += 1
def deposit(self, amount):
assert amount > 0, ValueError("Must deposit a positive amount")
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
def __str__(self):
rep = f"Bankaccount for {self.name}"
rep += f"\n\tAcc Num: {self.account_num}"
rep += f"\n\tBalance: €{self.balance:.2f}"
return rep
customer = BankAccount("Fred Jones", 99)
print(customer)
You need to def init as your first method. Thats where you specify cname, acnt_no etc.
you need to declare the variables inside the class first.
create the init() constructor to declare and initialize those variables

Changing the values of an instance of a class through another class in python

I have the classes Employee and Company
class Company:
employee_list = [
{"name":"rohan", "salary" : 50000, "number" : "9243485233", "working_days" : 300, "bonus" : "30%"}
]
def give_leaves(self, name, leaves_required):
if leaves_required < 5:
working_days = self.employee_list[0].get("working_days")
working_days -= leaves_required
self.employee_list[0]["working_days"] = working_days
print(self.employee_list)
else:
print("Leaves can't be granted")
class Employee:
def __init__(self,name, salary, number):
self.working_days = 300
self.bonus_percent = 30
self.name = name
self.salary_dollars = salary
self.number = number
def ask_for_leaves(self):
try:
leaves_required = int(input("How many days off are required?"))
print("Request sent to Company.")
Company.give_leaves(Company, self.name, leaves_required)
except ValueError:
pass
rohan = Employee("rohan", 50000, "9243485233")
rohan.ask_for_leaves()
When granting the Employee instance rohan leaves, and updating the working_days in the employee_list, I would like to also change the instance attribute working_days of rohan
You should add instance of Employee to employee_list - and this way you don't duplicate data.
You should rather create instance of class Company and send it to Employee and it should add itself to list employee_list.
# add company to employee
self.company = company
# add employee to company
self.company.employee_list.append(self)
And later Employee can use self.company to access functions in Company. And Company can use list employee_list to access infromation in every Employee
class Company:
def __init__(self, name):
self.name = name
self.employee_list = []
def give_leaves(self, employee, leaves_required):
if leaves_required < 5:
if employee.working_days >= leaves_required:
employee.working_days -= leaves_required
print('Working days:', employee.working_days)
else:
print('You don\'t have working days')
else:
print("Leaves can't be granted")
def list(self):
print(f'--- employees in {self.name} ---')
if not self.employee_list:
print('No employees')
else:
for employee in self.employee_list:
print('name:', employee.name, '| working days:', employee.working_days)
class Employee:
def __init__(self, name, salary, number, company):
self.working_days = 300
self.bonus_percent = 30
self.name = name
self.salary_dollars = salary
self.number = number
# add company to employee
self.company = company
# add employee to company
self.company.employee_list.append(self)
def ask_for_leaves(self, leaves_required):
try:
print("Request sent to Company.")
# send itself as first argument - so it will have direct access to data
self.company.give_leaves(self, leaves_required)
except ValueError as ex:
print('Exception:', ex)
# --- main ---
company = Company('MI6')
company.list()
rohan = Employee("rohan", 50000, "9243485233", company)
james_bond = Employee("james_bond", 500_000, "007", company)
company.list()
days = int(input("How many days off are required? "))
rohan.ask_for_leaves(days)
company.list()
Result:
--- employees in MI6 ---
No employees
--- employees in MI6 ---
name: rohan | working days: 300
name: james_bond | working days: 300
How many days off are required? 4
Request sent to Company.
Working days: 296
--- employees in MI6 ---
name: rohan | working days: 296
name: james_bond | working days: 300

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

Python, Attribute error [duplicate]

This question already has answers here:
What is the meaning of single and double underscore before an object name?
(18 answers)
Closed 8 years ago.
This is the Traceback I am getting :
Traceback (most recent call last):
File "D:\School\Programming ll\Week 4\2.py", line 42, in
main()
File "D:\School\Programming ll\Week 4\2.py", line 38, in main
print('Name: ',emp.name())
AttributeError: 'ProductionWorker' object has no attribute 'name'
Code:
class Employee(object):
def __init__(self,name,id_number):
self.__name = name
self.__id_number = id_number
def set_name(self, name):
self. __name = name
def set_id_number(self,id_number):
return self.__name
def get_id_number(self):
return self.__id_number
class ProductionWorker(Employee):
def __init__(self, name,id_number,shift_num,pay_rate):
Employee.__init__(self, name, id_number)
self.__shift_num = shift_num
self.__pay_rate = pay_rate
def set_shift_num(self, shift_num):
self.__shift_num= shift_num
def set_pay_rate(self, pay_rate):
self.__pay_rate = pay_rate
#accessor functions for shift_number and pay_rate
def get_shift_num(self):
return self.__shift_num
def get_pay_rate(self):
return self.__pay_rate
def main():
#get the values of employee name, number , shif_number and pay_rate from user.
print ('Enter the following information for the employee')
name=input('Name: ')
id_number=input('Employee number: ')
shift_num=input('Shift number: ')
pay_rate=input ('Pay rate: ')
emp = ProductionWorker(name,id_number,shift_num,pay_rate)
print('Details of employee are shown below: ')
print('Name: ',emp.name())
print('Employee Number: ',emp.get_id_number())
print('Shift Number: ',emp.get_shift_num())
print('Pay Rate: ',emp.get_pay_rate())
main()
Please help me , I have been banging my head for hours now. Thanks
ProductionWorker is not a member of Employee. try instead :
emp = ProductionWorker(name,id_number,shift_num,pay_rate)
You may add a method in the Employee class :
def name(self):
return self.__name
The best way would be to use properties : https://docs.python.org/2/library/functions.html#property

Categories