Is there a way to dynamically sort variables into classes? - python-3.x

I have these two Classes: "Employee" - the superclass and "Salesman" - a subclasss of "Employee".
And I have eric = ('Eric', 19, 'Salesman', 1700).
Can i use a function to check if Eric is a Salesman and dynamically assign him to either the "Employee" superclass or the "Salesman" subclass?
And how should I go about writing that?
I hope, my description of the problem wasn't too confusing.
class Employee():
'''the employee superclass'''
def __init__(self, name, age, occupation, monthly_pay):
self.isemployee = True
self.name = name
self.age = age
self.occ = occupation
self.pay = monthly_pay
class Salesman(Employee):
'''the Salesman subclass'''
def __init__(self):
self.issalesman = True

After some trial and error, and rewriting, this is what I came up with:
class Employee():
'''The employee superclass'''
def __init__(self, name, age, occupation, monthly_pay):
self.name = name
self.age = age
self.occ = occupation
self.pay = monthly_pay
class Salesman(Employee):
'''The Salesman subclass'''
def issalesman(self):
self.issalesman = True
def class_assigner(person):
if person[2] == 'Salesman':
person = Salesman(person[0], person[1], person[2], person[3])
else:
person = Employee(person[0], person[1], person[2], person[3])
return person
print(class_assigner(eric).occ)
Output:
Salesman
Is this a viable method, or will i run into problems later, if I, say for example start importing employee - data from a .txt or .csv file?

Related

How in Pyhton's OOP a class's method access to another class's method?

I am new to Python OOP and I am trying to learn the basics of Python OOP and I came across a video on YouTube that teaches the basics of it. The code is an example code from the video. I understood all of it but I am not able to understand how the class "Course's" "get_average_grade()" method is accessing the class "Student's" "get_grade()" method? Any help is highly appreciated.
class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade # 0-100
def get_grade(self): #<---- This method was used inside the Course class
return self.grade
class Course:
def __init__(self, name, max_students):
self.name = name
self.max_students = max_students
self.students = []
def add_student(self, student):
if len(self.students) < self.max_students:
self.students.append(student)
return True
return False
def get_average_grade(self):
value = 0
for student in self.students:
value = value + student.get_grade() #<---- This Method is from the Student class
return value / len(self.students)
s1 = Student("Tim", 19, 95)
s2 = Student("Bill", 19, 75)
s3 = Student("Jill", 19, 65)
course = Course("Science", 2)
course.add_student(s1)
course.add_student(s2)

Attribute Error in python, object has no attribute

I am new to inheritance in classes and for some reason, the attributes in this code don't seem to be sharing correctly. I'm not sure what the issue is.
class Person:
def __init__(self, name, age, occupation):
self.name = name
self.age = age
self.occupation = occupation
def say_hello(self):
print(f"Hello, my name is {self.name}.")
def say_age(self):
print(f"I am {self.age} years old.")
class Superhero(Person):
def __init__(self, name, age, occupation, secret_identity, nemesis):
self.secret_identity = secret_identity
self.nemesis = nemesis
hero = Superhero("Spider-Man", 17, "student", "Peter Parker", "Green Goblin")
print(hero.name())
It looks like you're not calling the super constructor in your Superhero class.
You should do as follow:
class Superhero(Person):
def __init__(self, name, age, occupation, secret_identity, nemesis):
super().__init__(name, age, occupation)
self.secret_identity = secret_identity
self.nemesis = nemesis
BTW: you didn't define a function named name. If you want to print the name you should remove the (), e.g print(hero.name)

How to remove an object from list by a value

My problem is that I created a list of students with name and number. The task is now to remove a student by his number. My problem is that my code doesn't work.
Another problem is that it always shows the memory address instead of the value of the object.
Thanks in advance
class Student:
def __init__(self, name, number):
self.name = name
self.number = number
from .student import Student
class Course:
def __init__(self, name, code, credit, student_limit):
self.name = name
self.code = code
self.credit = credit
self.student_limit = student_limit
students = []
def add_student(self, new_student):
self.student = new_student
self.students.append(new_student)
print("Student added" +str(self.students))
def remove_student_by_number(self, student_number):
self.student_number = student_number
if student_number in self.students: self.students.remove(student_number)
print("Student removed" + str(self.students))
from .course import Course
class Department:
def __init__(self, name, code):
self.name = name
self.code = code
courses = []
def add_course(self, course):
self.course = course
self.courses.append(course)
print("Course added" +str(self.courses))
from python import *
def main():
alice = Student("Alice", 1336)
bob = Student("Bob", 1337)
math_dept = Department("Mathematics and Applied Mathematics", "MAM")
math_course = Course("Mathematics 1000", "MAM1000W", 1, 10)
math_dept.add_course(math_course)
math_course.add_student(bob)
math_course.add_student(alice)
math_course.remove_student_by_number(alice.number)
if __name__ == "__main__":
main()
self.students is a list of Student instance so it will print the instance's memory address if the method __str__ is not implemented (see here for example). You should try to print each property like student.name or student.number explicitly.
Anyway you are trying to find student_number in list of Student so of course it will never run the remove line. Instead use if student_number in [student.number for student in self.students] which is looking up the student's number list, not the student list itself. However in this case, you also want to remove the student with the student_number as the input so you may need to use a loop like this:
def remove_student_by_number(self, student_number):
for student in self.students:
if student.number == student_number:
print("Student removed" + str(student.name))
self.students.remove(student)
break

How to connect patient class with doctor class?

so I'm working on a problem I found online just to practice my python coding skills and I got stuck somewhere along the line. So I was trying to list all the patient name with the one of the class definition called print_list_of_patients. However, I don't know how to link the patient with the attribute so that I could just refer to the name based on the date of their appointment
I tried to combine each patient into tuples, dict but I still couldn't get what I'm looking for. Basically, I was trying to group the patient class so that every time I look at the appointment date, I can access their name and their sickness as well.
class Doctor:
def __init__(self, name):
self.name = name
self.list_of_patient = []
self.availability = []
def __str__(self):
return "Hi, this is Dr. {a}".format(a=self.name)
def add_patient(self, patient):
self.list_of_patient.
def remove_patient(self, patient):
for dates in self.availability:
if len(self.list_of_patient) == 0 and self.availability[dates]:
print("There is no patient left")
else:
self.list_of_patient.remove(patient.name)
def add_days(self, *dates):
self.availability.append(dates)
def remove_days(self, *date):
for num in range(len(self.availability)):
if date == self.availability:
self.availability.remove(date)
def print_list_of_patient(self, date):
print("Dr. {a} patient's list for {b}:\n".format(a=self.name, b=date))
class Patient:
def __init__(self, name, sickness, date_of_appointment):
self.name = name
self.sickness = sickness
def __str__(self):
return "Name: {a}\n Sickness: {b}\n\n".format(a=self.name, b=self.sickness)
def set_up_appointment(doctor, patient):
"""
set_up_appointment(doctor, patient, date)
doctor = variable name (unique ID)
patient = variable name (unique ID)
:return:
"""
doctor.add_patient(patient)
def cancel_an_appointment(doctor, patient):
"""
cancel_an_appointment(doctor, patient)
doctor = variable name (unique ID)
patient = variable name (unique ID)
:return:
"""
for names in range(len(doctor.number_of_patient)):
if patient.name == doctor.number_of_patient[names].name:
doctor.remove_patient()

Why do i get a type error when using super()?

I just started learning about classes and inheritance in Python 3. I want to print the name of a student, which is inherited from the superclass Person. Unfortunately I keep getting a TypError.
code:
class Person(object):
def __init__(self, name="Mike", age = 25, place_of_birth="Stockholm"):
self.age = age
self.name = name
self.place_of_birth = place_of_birth
class Student(Person):
def __init__(self, name, age, university = "University of Stockholm", gpa = 8):
super().__init__(name, age)
self.university = university
self.gpa = gpa
I then like to print the name of the student by calling:
student1 = Student()
print(student1.name)
But I keep getting this error message:
Traceback (most recent call last):
TypeError: init() missing 2 required positional arguments: 'name' and 'age'
If you want Student to always default to the name and age of the Parent class then you don't want Student to take a name and age value.
class Student(Person):
def __init__(self, university = "University of Stockholm", gpa = 8):
super().__init__() # runs parent __init__ taking no values
self.university = university
self.gpa = gpa
>>> student1 = Student()
>>> student1.name
'Mike'
>>> student1.age
25
When you use super().__init__(name, age) you are wanting to pass the name and age given to the Student class to the Parent class. But since you don't want to pass anything it is getting errors.
Now, if you want the Student class to be able to take values as well as default to the ones provided by the parent class you can do this.
class Student(Person):
def __init__(self, name = None, age = None, university = "University of Stockholm", gpa = 8):
if name is None and age is None:
super().__init__()
else:
super().__init__(name, age)
self.university = university
self.gpa = gpa
What happens here is if no name or age is provided if name is None and age is None then it defaults to the values from Person class. However if both the name and age are provided, then it will use those values.
>>> student1 = Student()
>>> student1.name
'Mike'
>>> student1.age
25
>>> student2 = Student('Bill', 19)
>>> student2.name
'Bill'
>>> student2.age
19
The __init__() method of Student takes 2 positional arguments: name and age. You need to specify those arguments when creating a new instance:
student1 = Student('eppe2000', 20)
print(student1.name)
If you instead want the class Student to default to class Person default arguments, in case they have not been specified, you can do it like this:
class Person(object):
def __init__(self, name="Mike", age=25, place_of_birth="Stockholm"):
self.age = age
self.name = name
self.place_of_birth = place_of_birth
class Student(Person):
def __init__(self, university="University of Stockholm", gpa=8, **kwargs):
super().__init__(**kwargs)
self.university = university
self.gpa = gpa
>>> s = Student()
>>> s.name
'Mike'
>>> s = Student(name="Daniele")
>>> s.name
'Daniele'
Basically you forward all the keywords arguments that are unknown to the class Student to its parent class. Not that if you specify an invalid keyword (i.e: 'surname') you will get a TypeError because neither Student or Person specify a keyword argument with key 'surname'.
If you need info about **kwargs check this post: https://stackoverflow.com/a/36908/3477005

Resources