How to use class attribute as instance attribute in Python? [duplicate] - python

This question already has answers here:
python class attribute
(3 answers)
List as class attribute
(2 answers)
Closed 1 year ago.
I am new to Python programming and I was coding the following script to increase my understanding of Pyhton OOP.
# Python OOP
class Employee:
num_of_emps = 0
raise_amt = 1.04
def __init__(self, first_name, last_name, pay):
self.first_name = first_name
self.last_name = last_name
self.pay = pay
self.email = first_name.lower() + '.' + last_name.lower() + '#company.com'
Employee.num_of_emps += 1
def fullname(self):
return self.first + ' ' + self.last
def apply_raise(self):
self.pay = int(self.pay * self.raise_amt)
#classmethod
def from_string(cls, emp_str):
name, surname, pay = emp_str.split('-')
return cls(name, surname, pay)
class Developer(Employee):
raise_amt = 1.01 # overriding raise_amt
def __init__(self, first_name, last_name, pay, prog_lang=None):
super().__init__(first_name, last_name, pay)
self.prog_lang = prog_lang
#classmethod
def with_prog_lang(cls, first_name, last_name, pay, prog_lang):
return cls(first_name, last_name, pay, prog_lang)
#classmethod
def from_string_kebab_case(cls, emp_str):
first_name, last_name, pay, prog_lang = emp_str.split('-')
return cls(first_name, last_name, pay, prog_lang)
class Manager(Employee):
raise_amt = 1.1
supervised_employee = []
def __init__(self, first_name, last_name, pay, employees=None):
super().__init__(first_name, last_name, pay)
if employees is not None:
self.supervised_employee.append(employees)
def add_emp(self, employee):
if employee not in self.supervised_employee:
self.supervised_employee.append(employee)
def remove_emp(self, employee):
if employee in self.supervised_employee:
self.supervised_employee.pop()
def show_employees(self):
if (len(self.supervised_employee) == 0):
print(f"{self.first_name} is managing no one")
else:
print(f"{self.first_name} is managing ", end='')
output = ''
for emp in self.supervised_employee:
output = output + emp + ' ,'
print(f"{output}")
emp1 = Developer('Burak', 'Aksoy', 5000)
manager1 = Manager('Ahmet', 'Nazli', 10000, 'Burak')
manager1.add_emp('John')
manager2 = Manager('Faruk', 'Tuncer', 10000)
print(manager1.supervised_employee)
manager1.show_employees()
manager2.show_employees()
Here, I have the following output as I run the code ->
{'first_name': 'Ahmet', 'last_name': 'Nazli', 'pay': 10000, 'email': 'ahmet.nazli#company.com'}
['Burak', 'Harun']
Ahmet is managing Burak ,John ,
Faruk is managing Burak ,John ,
When I add 'Burak' and 'John' as employees to manager1, I see that manager2 is also affected by this, but I don't want this to happen.. How do you think I can fix this?
Any help is appreciated.
Best.

Related

Issue printing out __str__() function for location of a list type object

When printing out the str() function for the Manager() class the employees list prints out the location of the objects in memory instead of in type(str) format. The rest of the Manager str prints out fine, but I can't figure out how to get the employees list to print out. I'm just using the GUI to test aspects of the code for now.
Thank you in advance for your time.
Image of incorrect output on GUI
import random
from random import randint
from tkinter import *
import tkinter as tk
from tkinter import ttk
class Employees(object):
'''
'''
num_emps = 0
def __init__(self, first_name, last_name, pay, emp_id):
self.first_name = first_name
self.last_name = last_name
self.pay = pay
self.emp_id = self.IdMaker()
Employees.num_emps += 1
def get_first_name(self): #Retrieves First Name
return self.first_name
def get_last_name(self): #Retrieves Last Name
return self.last_name
def get_full_name(self): #Retrieves Full Name
return '{} {}'.format(self.first_name, self.last_name)
def __str__(self):
return '{self.emp_id}: {self.first_name} {self.last_name}'.format(self=self)
#####---ID CLASS---#####
class IdMaker():
'''
'''
def __init__(self):
self.emp_id = 'emp_' + ''.join(str(random.randint(0, 9)) for x in range(12))
self.food_id = 'food_' + ''.join(str(random.randint(0, 9)) for x in range(12))
self.sanitation_id = 'sani_' + ''.join(str(random.randint(0, 9)) for x in range(12))
self.dinnerWare_id = 'dWare_' + ''.join(str(random.randint(0, 9)) for x in range(12))
def __str__(self):
if isinstance(self.emp_id, object):
return '{self.emp_id}'.format(self=self)
elif isinstance(self.food_id, object):
return 'food_{self.food_id}'.format(self=self)
elif isinstance(self.sanitation_id, object):
return 'sani_{self.sanitation_id}'.format(self=self)
elif isinstance(self.dinnerWare_id, object):
return 'sani_{self.dinnerWare_id}'.format(self=self)
else:
print('No such object')
#-----------------------------------------------------------------------------
class Manager(Employees):
def __init__(self, first_name, last_name, pay, emp_id, employees=None):
super().__init__(first_name, last_name, pay, emp_id)
# if schedule is None: #Schedule
# self.schedule = {}
# else:
# self.schedule = schedule
if employees is None: #Employees working for Manager
self.employees = []
else:
self.employees = employees
def add_emp(self, emp):
if emp not in self.employees:
self.employees.append(emp)
def remove_emp(self, emp):
if emp in self.employees:
self.employees.remove(emp)
def print_emps(self):
for emp in self.employees:
print(emp.get_full_name())
def __str__(self):
return '{self.emp_id}: {self.first_name} {self.last_name} |Pay - ${self.pay} - {self.employees}'.format(self=self)
class FOH(Manager):
def __init__(self, first_name, last_name, pay, emp_id):
Employees.__init__(self, first_name, last_name, pay, emp_id)
self.pay = pay
# if schedule is None: #Schedule
# self.schedule = {}
# else:
# self.schedule = schedule
def __str__(self):
return '{self.emp_id}: {self.first_name} {self.last_name} |Pay - ${self.pay}'.format(self=self)
class BOH(Manager):
def __init__(self, first_name, last_name, pay, emp_id):
Employees.__init__(self, first_name, last_name, pay, emp_id)
self.pay = pay
# if schedule is None: #Schedule
# self.schedule = {}
# else:
# self.schedule = schedule
def __str__(self):
return '{self.emp_id}: {self.first_name} {self.last_name} |Pay - ${self.pay}'.format(self=self)
foh_1 = FOH('Rebecca', 'Peters', 60000, None)
foh_2 = FOH('Becca', 'Peters', 60000, None)
boh_3 = BOH('Beckles', 'Peters', 60000, None)
mgr_1 = Manager('Sean', 'Sheaffer', 90000, None, [foh_1, foh_2, boh_3])
# mgr_1.add_emp([foh_2])
# mgr_1.add_emp([boh_3])
mgr_2 = Manager('Becky', 'Peters', 100000, None, [boh_3])
mgr_2.print_emps()
mgr_1.print_emps()
#####---GUI CLASS---#####
root = Tk()
root.title('DigiSous')
root.geometry("600x200")
# Creates tab control
tabControl = ttk.Notebook(root)
class GUI(Manager):
def __init__(self, master, first_name, last_name, pay, emp_id):
super().__init__(first_name, last_name, pay, emp_id)
my_frame = Frame(master)
my_frame.pack()
#Find Employees working for Manager
self.find_mgr_emps = Button(master, text="Employees", command=self.manager_emps)
self.find_mgr_emps.pack(pady=20)
self.find_mgr_emps_Entry = Entry(master, width=90, borderwidth=5)
self.find_mgr_emps_Entry.pack(pady=10)
def manager_emps(self):
self.find_mgr_emps_Entry.delete(0, END)
mgr_emps = mgr_1
self.find_mgr_emps_Entry.insert(0, mgr_emps)
#-----------------------------------------------------------------------------
e = GUI(root, None, None, None, None)
root.mainloop()
Whenever you print a list, you will see the __repr__ of those objects instead of __str__, so one way could be to override the __repr__ method to get your desired output, as for example:
def __repr__(self):
return str(self)
Another way could be to use a list comprehension when you format your string as follows:
class Manager(Employees):
def __str__(self):
return '{self.emp_id}: {self.first_name} {self.last_name} |Pay - ${self.pay} - {[str(x) for x in self.employees]}'.format(self=self)

Class is returning None after the result

I have a class User and a subclass Admin that I am trying to work on, but when I try to call an instance of them I keep getting None returned after the result
class User:
def __init__(self, first_name, last_name, age, height):
self.first_name = first_name
self.last_name = last_name
self.age = age
self.height = height
def describe_user(self):
print(f"{self.first_name} {self.last_name}\n{self.age} " \
f"years old\n{self.height} cm tall")
def greet_user(self):
print(f"Hi, {self.first_name} {self.last_name}! ")
class Admin(User):
def __init__(self, first_name, last_name, age, height):
super().__init__(first_name, last_name, age, height)
self.privileges = ['post', 'delete post', 'ban user']
def show_privileges(self):
print(f"{self.first_name} can:")
for item in self.privileges:
print(item)
person = Admin('John', 'Doe', 20, 180)
print(person.describe_user())
print(person.show_privileges())
John Doe
20 years old
180 cm tall
None
John can:
post
delete post
ban user
None
I am trying to find out why this happens and how to fix it
person.describe_user() returns None implicitly since it doesn't have a return statement within the function body(it only prints a value). This causes print(person.describe_user()) to print None.
The solution is to just write person.describe_user() without the extra print(), and similarly for the following line.
describe_user and show_privileges do their own printing; they don't have a return value, so they implicitly return None. Get rid of the print around the call to each of them, making the end of your code just:
person = Admin('John', 'Doe', 20, 180)
person.describe_user()
person.show_privileges()
and you won't print their useless return values (None).

Result of the __init__(self) related method is not showing up

class Employee(object):
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
self.email = first + '.' + last + '#company.com'
def fullname(self):
return '{} {}'.format(self.first, self.last)
def pay_raise(self):
self.pay = int(self.pay * 1.04)
emp_1 = Employee("Mark", "Johnson", 50000)
emp_1.pay_raise()
When I write that emp_1.pay_raise() phrase or emp_1.fullname() i dont get any results or any errors either after pressing "run" or "debug" in pycharm. Can you notice any mistakes in my code? I will very appereciate.
You are not printing out any of the "results" from executing the methods. Try this:
class Employee(object):
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
self.email = first + '.' + last + '#company.com'
def fullname(self):
return '{} {}'.format(self.first, self.last)
def pay_raise(self):
self.pay = int(self.pay * 1.04)
emp_1 = Employee("Mark", "Johnson", 50000)
print(emp_1.fullname())
emp_1.pay_raise()
print(emp_1.pay)

(Python Derived Classes) Not getting the correct output

This is my desired output:
Name: Smith, Age: 20, ID: 9999
Here is my code so far
class PersonData:
def __init__(self):
self.last_name = ''
self.age_years = 0
def set_name(self, user_name):
self.last_name = user_name
def set_age(self, num_years):
self.age_years = num_years
# Other parts omitted
def print_all(self):
output_str = 'Name: ' + self.last_name + ', Age: ' + str(self.age_years)
return output_str
class StudentData(PersonData):
def __init__(self):
PersonData.__init__(self) # Call base class constructor
self.id_num = 0
def set_id(self, student_id):
self.id_num = student_id
def get_id(self):
return self.id_num
course_student = StudentData()
course_student = StudentData()
course_student.get_id(9999)
course_student.set_age(20)
course_student.set_name("Smith")
print('%s, ID: %s' % (course_student.print_all(), course_student.get_id()))
At the moment, it isn't running. I would really appreciate it if someone could help out. It is returning a type error for line 34, and I am not sure how to correct it. Any help would be greatly appreciated.
You're invoking the parent init wrongly there...
Here's how you're supposed to do it:
class PersonData:
def __init__(self):
self.last_name = ''
self.age_years = 0
def set_name(self, user_name):
self.last_name = user_name
def set_age(self, num_years):
self.age_years = num_years
# Other parts omitted
def print_all(self):
output_str = 'Name: ' + self.last_name + ', Age: ' + str(self.age_years)
return output_str
class StudentData(PersonData):
def __init__(self):
super().__init__() # Call base class constructor
self.id_num = 0
def set_id(self, student_id):
self.id_num = student_id
def get_id(self):
return self.id_num
course_student = StudentData()
course_student = StudentData()
course_student.set_id(9999)
course_student.set_age(20)
course_student.set_name("Smith")
print('%s, ID: %s' % (course_student.print_all(), course_student.get_id()))
I also noticed that in the execution, you were calling course_student.get_id(9999) but I think you meant course_student.set_id(9999)

Trying Python 3 code for this simple Employee object and I'm stuck

Here's the simple python 3 object code from the web that is not platform dependent.. I cannot get working
class Employee:
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
self.email = first + '.' + last + '#company.com'
def fullname(self):
return '{}{}'.format(self.first, self.last)
emp_1 = Employee('John','Doe','80000')
emp_2 = Employee('Jane','Foo','90000')
emp_2.fullname()
print (Employee.fullname(emp_1))
print (emp_2.fullname())
The error I get is as follows:
NameError Traceback (most recent call last)
in ()
----> 1 class Employee:
2
3 def init(self, first, last, pay):
4 self.first = first
5 self.last = last
in Employee()
10 return '{}{}'.format(self.first, self.last)
11
---> 12 emp_1 = Employee('John','Doe','80000')
13 emp_2 = Employee('Jane','Foo','90000')
14
NameError: name 'Employee' is not defined
Indentation is crucial in Python. Try the below code.
Your class instances must be defined outside the class itself. This is recognised by there being no indentation for definitions of emp_1 and emp_2.
class Employee:
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
self.email = first + '.' + last + '#company.com'
def fullname(self):
return '{}{}'.format(self.first, self.last)
emp_1 = Employee('John','Doe','80000')
emp_2 = Employee('Jane','Foo','90000')
emp_2.fullname()
print(Employee.fullname(emp_1))
print(emp_2.fullname())
This is simply an indentation error.
Python defines scopes like classes, methods and other blocks by indentation. Usually 4 spaces are used.
Since you put your instantiation of emp_1 and emp_2 with the same indentation as the class's methods they are literally part of the class.
What you probably meant was:
class Employee:
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
self.email = first + '.' + last + '#company.com'
def fullname(self):
return '{}{}'.format(self.first, self.last)
emp_1 = Employee('John','Doe','80000')
emp_2 = Employee('Jane','Foo','90000')
emp_2.fullname()
print (Employee.fullname(emp_1))
print (emp_2.fullname())
class Employee:
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.pay = pay
self.email = first + '.' + last + '#company.com'
def fullname(self):
return '{}{}'.format(self.first, self.last)
def main():
emp_1 = Employee('John','Doe','80000')
emp_2 = Employee('Jane','Foo','90000')
emp_2.fullname()
print (Employee.fullname(emp_1))
print (emp_2.fullname())
if __name__ == '__main__':
main()

Categories

Resources