Python input Job Code - python

I'm Code doesn't seem to work, I am trying to get input of a job, category, and salary, and store the input
class Jobs:
def GetJob(self):
name = raw_input('Enter a Job Title: ')
category = raw_input('Enter what Category that Job is: ')
salary = raw_input('Enter the salary of that Job: ')
print name,category, salary
def __init__(self,name,category,salary):
self.name = Jobs.GetJob(name)
self.category = Jobs.GetJob(category)
self.salary = Jobs.GetJob(salary)
GetJob = Jobs()
print GetJob

Your code is totally out of good OOP practices, and the first part eandersson's answer too…
A class has for role to store values, get/set them and return (or apply) transformations to its encapsulated values. What you tried to achieve is totally nonsense: you're calling the GetJob method of the Jobs class inside another method. It could work if you would have written:
def __init__(self,name…):
self.name = Jobs.GetJob(self, name)
…
But that would be a wrong way to design your program. You'd better stick your class to hold your values and making it good at that, and make another function that helps populate your class:
class Jobs:
def __init__(self, name, category, salary):
self.name = name
self.category = category
self.salary = salary
def __repr__(self):
return "Jobs<%s,%s,%s>" % (self.name, self.category, self.salary)
def GetJob():
name = raw_input('Enter a Job Title: ')
category = raw_input('Enter what Category that Job is: ')
salary = raw_input('Enter the salary of that Job: ')
return Jobs(name, category, salary)
print GetJob()
I do not agree with eandersson's approach because it deceives the purpose of the constructor, by directly calling the GetJob method. Then GetJob is not useful. And one would want to be able to use the Job class without always having the raw inputs at construction. EDIT: valid only as a comment on the first part of his answer.
And finally, I think that you really misunderstands a lot about programming. You should better read thoroughly a python course like the ones on http://wiki.python.org/moin/BeginnersGuide/NonProgrammers, because there's really a lot of concepts you ignored to be able to write something like that.
go have a look at:
http://hetland.org/writing/instant-hacking.html
http://www.learnpython.org/
http://cscircles.cemc.uwaterloo.ca/
http://learnpythonthehardway.org/book/

Related

Trying to wrap my head around observer class

I'm trying to understand an observer class, but I don't understand how to implement it in practice.
I have a class that has 4 functions in relation to a .txt database- add student, delete student, sort and show student database, and search a student. I want it to send out an automatic message to all students when another student is added or deleted.
This is what I have so far, based off a guide I've been looking at:
class ObservableEvent:
def __init__(self):
self.students = []
def register_student(self, student):
self.students.append(student)
def notify_allStudents(self, *args, **kwargs):
for student in self.students:
student.notify(self, *args, **kwargs)
class Observer:
def __init__(self, observable):
observable.register_student(self)
def notify(self, message, observable):
print("Got", message, "From", observable)
subject = ObservableEvent()
student = Observer(subject)
I think its just the last part I'm having the biggest issue with (I hope), concerning the notify_allStudents part. Whenever I try to pass more than 1 positional argument, it doesn't work. So far I have this:
class Student():
def __init__(self, data):
self.data = data
pass
def AddStudent(self, data):
firstName = input('First Name: ')
lastName = input("\nLast Name: ")
email = input('\nEmail Address: ')
campus = input('\nCampus: ')
year = '22'
generated_id = firstName[0:3] + lastName[0:3] + year
newStudent = [generated_id, firstName, lastName, email, campus]
f = open(data, "a")
f.write('\n')
for info in newStudent:
f.write(info)
f.write('\t')
f.close()
pass
Then here is where I have the above ObserverEvent and Observer classes.
And here is the rest:
ans=True
while ans:
print ("""
---------------------------------------------------
Welcome to the QUICK SORT / LINEAR SEARCH Program
1.ADD NEW STUDENT
2.DELETE STUDENT
3.SHOW STUDENTS
4.SEARCH STUDENT
5.ADD COURSE TO STUDENT
Type EXIT to quit the application
""")
ans=input("What would you like to do? ")
if ans=="1":
print("""
*******************
STUDENT ADD MENU
*******************
""")
Student.AddStudent(input, "studentMockData_AS2.txt")
print("\nStudent Added")
subject.notify_allStudents("A student has been added to the database.")
I'm currently getting this in the console: Got <__main__.ObservableEvent object at 0x00000154909BB460> From A student has been added to the database.
I'm honestly really lost on this. The example I was given was subject.notify_observers("test", kw="python"), but the *args and **kwargs are really throwing me. It throws an error of too many positional arguments if I include more than 1, but I thought the whole point of kwargs was to input more than 1. I'm also not sure why I would need to use a dict in this scenario. I don't even understand what I'm not understanding about this, but clearly I'm not doing it right. Any assistance would be hugely appreciated.
EDIT: I'm aware that my class Student is badly done, but I have to leave it as is.

I dont know where I'm going wrong trying to create an object in a subclass through inputs

I've tried many different things so it's a little all over the place, please help
I've been able to make the first class and then in a different file create some objects for it, but for this subclass I need to use user input and I just can't figure it out.
I have made it so the shift input has to be a 1 or 2 for a day or night shift, I just don't have the knowledge for this.
class Employee:
def __init__(self, name, id, dept, title):
self.__name = name
self.__id = id
self.__dept = dept
self.__title = title
def get_name(self):
return self.__name
def get_id(self):
return self.__id
def get_dept(self):
return self.__dept
def get_title(self):
return self.__title
def __str__(self):
result = ""
result += "Name: " + self.get_name() + "\tID Number: " + str(self.get_id()) + \
"\tDepartment: " + self.get_dept() + "\tJob Title:" + self.get_title()
return result
class ShiftEmployee(Employee):
def __init__(self, name, id, dept, title, shift, pay):
Employee.__init__(self, name, id, dept, title)
self.__shift = shift
self.__pay = pay
#classmethod
def inputs(self):
self.__name = input("Enter name: ")
self.__id = input("Enter ID number: ")
self.__dept = input("Enter department: ")
self.__title = input("Enter Jobe title: ")
self.__shift = input("Enter shift: ")
self.__pay = input("Enter hourly pay: ")
#set_shift(self, shift):
#self.__shift = shift
#def set_pay(self, pay):
#self.__pay = pay
def get_shift(self, shift):
if self.__shift == 1:
return "Day"
elif self.__shift == 0:
return "Night"
else:
return "Invalid entry"
def get_pay(self, pay):
return self.__pay
def __str__(self):
result = ""
#result += Employee.__str__(self)
result += "Name: " + self.get_name(ShiftEmployee) + "\tID Number: " + str(self.get_id(ShiftEmployee)) + \
"\tDepartment: " + self.get_dept(ShiftEmployee) + "\tJob Title:" + self.get_title(ShiftEmployee) + \
"\tShift: " + self.get_shift(ShiftEmployee) + "\tHourly Pay: " + str(self.get_pay(ShiftEmployee))
return result
shift_emp = ShiftEmployee
shift_emp.inputs()
print(shift_emp.__str__(ShiftEmployee))
Don't use a classmethod because
A class method is a method that’s shared among all objects.
Though python itself does not force this behavior, your use of self in the inputs definition indicates that you are not doing what you think. the parameter is traditionally named cls in #classmethod-annotated methods, because the object you're referring to inside the body is not an instance of the class, but the class object itself. This means if you have multiple ShiftEmployee objects, they're going to be writing their data to the same variables. This is not what you want to happen.
you are not instantiating a ShiftEmployee object with shift_emp = ShiftEmployee, but rather assigning the class to the variable shift_emp, which is not what you want to do. so if you remove the #classmethod annotation, I think what you want is
shift_emp = ShiftEmployee() # __init__ gets called when you use this constructor invocation
shift_emp.inputs()
print(shift_emp)
Your __str__ methods don't make a lot of sense. You are passing the class object to each getter, which doesn't seem like it's what you'd want to do. The class object defines the class, what you want are the instances of the class. It's an important, if initially confusing distinction. Posting the error you get would help, but here's what I would expect the methods to look like. I'm not using the getters, because this is internal access, but you can use them instead of directly referring to the state variables if you prefer.
# Employee
def __str__(self):
return f"Name: {self.__name} ID Number: {self.__id} Department: {self.__dept} Job Title: {self.__title}"
# ShiftEmployee
def __str__(self):
return super(ShiftEmployee, self).__str__() + f" Shift: {self.__shift} Hourly Pay: {self.__pay}"
So what's going on here? For one thing, we use format strings because they are easier to work with and exactly the thing you wanted. Then we're using the superclass (Employee) to provide the shared functionality, and using the descendent class to enrich with the ShiftEmployee-only data. I skipped the accessor methods because they're redundant when accessing "private" data from inside the class members. Note that this won't quite do what you expect, either, w.r.t. the shift value that gets printed -- it's going to print the int, not "Night" or "Day". This is where your accessor method comes into play, except that your accessor has an extraneous parameter, shift. So you'd have to remove that value.
Please use the following way to initialize the class and printing the class,
shift_emp = ShiftEmployee() # Added Parenthesis
shift_emp.inputs()
print(str(shift_emp)) # Pass class object to inbuilt str() method to get output from __str__() method from class

How to input data in classes in python, if number of students I want to input is not known

I want to input data in a class. I don't know the number of students I want to input. I can only write p1.name="John" p2.name="Jack" etc but if I want to input more students I have to write p3,p4,p5...
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p1 = Person
p1.name="John"
p1.age=15
print(p1.name)
print(p1.age)
Is there a method to work like with arrays for example p[0].name="John"....... p[123].name="Jack" or something like that... Sorry for my bad english
You probably meant
p1 = Person('John', 15)
p2 = Person('Jack', 42)
If you needed an arbitrary number of objects, you can store them in a data structure like
people = [Person('John', 15), Person('Jack', 42)]
for person in people:
print(person.name)
You can read data into that array as well-
people = []
with open('people.txt') as f:
for line in f:
name, age = line.split()
people.append(Person(name, age))
But my advice would be to find a more introductory tutorial to follow, you're going to struggle :)
Sounds like you need a list.
A list is a data structure that you can use for zero or more elements, and you can access each element by iteration or by indexing the list.
You can do something like this:
persons = [
Person("John", 15),
Person("Adele", 16),
...
]
and then you can access each person by an index: persons[0] will give you Jonh, and persons[1] will give Adele.
if your objective is to store the students in an array-like structure, then you can definitely do this in Python. What you're currently doing is instantiating a new class object for each student. While this is totally valid, it may not be appropriate for the task you're trying to achieve.
Before mastering classes, I'd recommend familiarising yourself with python data structures like dictionaries, lists and tuples.
Just another idea. You could store all of the students in a dictionary that is contained within a class. Wrapping the dictionary in a class will let you add or fetch students very easily.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Classroom:
def __init__(self):
self.students = {}
def add_student(self, student):
self.students[student.name] = student
def get_student(self, name):
return self.students[name]
classroom = Classroom();
classroom.add_student(Person("John", 12))
classroom.add_student(Person("Sarah", 13))
print(classroom.get_student("Sarah").age)
#Output
#13
def main():
classroom = Classroom()
n = input("How many students would you like yo add? ")
for i in range(int(n)):
classroom.add_student(Person(input("Enter Name: "), int(input("Enter Age: "))))

Python Class and encapsulation methods

I'm new to OOP and this is my first shot at creating a Python class. I am trying to make my 3 variables private and so that only the methods update the info (enforce encapsulation). It seems that if I remove the setters and getters methods from my class, it has no impact on my code (must be the initializer method doing the work?). What can I do to improve this? Thanks.
Edit- i've updated my code and removed the init. My getters are not working now.
#Instantiate a new Pet Instance.
myPet = Pet()
#Get input from user.
myPet.setName = input("Enter the pet's name: ")
myPet.setTypes = input("Enter the pet's type (Dog, Cat, Bird, etc.): ")
myPet.setAge = input("Enter the pet's age (in years): ")
while myPet.setAge.isalpha():
print()
print("Age cannot contain numbers. Try again.")
myPet.setAge = input("Enter the pet's age (in years): ")
#Call the showPetInfo module using new instanced object.
myPet.showPetInfo()
class Pet:
#Fields of the Pet Class.
__PetName = ""
__PetType = ""
__PetAge = ""
#Setter methods.
def setName(self,name):
self.__PetName = name
def setTypes(self,types):
self.__PetType = types
def setAge(self,age):
self.__PetAge = age
#Getter methods.
#property
def getName(self):
return self.__PetName
#property
def getType(self):
return self.__PetType
#property
def getAge(self):
return self.__PetAge
def showPetInfo(self):
print("\n \n \n \n")
print("Here is your pet's information. Your pet's name is {}, it is a {} and it is {} years old.".format(self.getName,self.getType,self.getAge))
main()
you are unfortunately right, they use to say setters/getters are contracts doing restriction for adults... (if I tell you "dont touch it" then you shoulntd touch it) but there is nothing restricting you and you can modify them!
same "feature" can be observed with "constants"... do in the jupyther or the terminal this
import math
math.pi = 1
a = math.pi
a
math.pi
and you will see that you now modified the constant pi value to 1
many sugest to usse properties but that is not a capsulation at all, that is just sugar syntax for the same "adults contract" IMHO :)
so to your question
What can I do to improve this?
document the code you are writing so the other part using it is aware about how the code, instances states in objects must be handled

Python class and array interaction

So the basic idea is to make a "phonebook" type deal using classes and I'm not sure how it would interact with arrays.
class Person:
name = None
b_year = None
phone = None
So that is supposed to be the base. Then I want to be able to use
array[0].name #The name of the first person
array[1].phone #Number of the second person etc.
What I'm not sure about is how the get this interaction between the two. Any tips would be appreciated.
Thanks in advance!
class Person:
def __init__(self, name, b_year, phone):
self.name = name
self.b_year = b_year
self.phone = phone
p1 = Person(name="Jedrzej", b_year="1882", phone="321432555")
p2 = Person(name="Michael", b_year="1282", phone="321432553")
arr = [p1, p2]
print(arr[0].name)
This prints Jedrzej for me.
I think you should read about classes in Python, for example here:
http://www.diveintopython.net/object_oriented_framework/defining_classes.html

Categories