Using classes in Python - python

If I have 5 pieces of relevant data, I think it's fair to use a class in order to sort data effectively. However, I need to add these vars to a list.
If I have class "student(name, grade, attendance)", and I'm appending these values to a list, what would that look like?

# student class, inits with name and student id
class Student:
def __init__(self,name,grade, attendance):
self.name = name
self.grade = grade
self.attendance = attendance
def __str__(self):
return self.name
# list of students
students = []
# creates two students
s1 = Student('terry', 99, 99)
s2 = Student('jack', 42, 1)
# add students in the list
students.append(s1)
students.append(s2)
print students

Related

How to use For loop to print all items in python class

I have created a new class:
testing.py:
class student:
def __init__(self, name, major, gpa):
self.nm = name
self.mj = major
self.gp = gpa
then, I move to my working file testing.py:
from testing import student
student1=student("Marcos","Physics",3.99)
student2=student("Phillyp","Biology",2.99)
student3=student("Naim", "Architecture", 3.42)
for k in range(1,4):
print(student(k).gp) <------- how do I merge this string with int!?!?
my final aim is to print out ALL the gpa of all students, so I know I need to do
print(student1.gp)
print(student2.gp)
print(student3.gp)
So how can I concatenate the k into the variable name to produce student1.gp, student2.gp etc?
Thank you all so much!
instead of this for k in range(1,4): you want to iterate over a list of all of your students:
students = [student1, student2, student3]
for student in students:
print(student.gp)
EDIT
If you want to be able to reference the students by name, store them in a dict:
students = {'student1': student("Marcos","Physics",3.99),
'student2': student("Phillyp","Biology",2.99),
'student3': student("Naim", "Architecture", 3.42)}
for i in range(1, 4):
print(students[f'student{i}'].gp)
# if less than python 3.6
# print(students['student{}'.format(i)].gp)
What you should be doing is putting all the objects in list. E.g.
from testing import student
student1 = student("Marcos","Physics",3.99)
student2 = student("Phillyp","Biology",2.99)
student3 = student("Naim", "Architecture", 3.42)
students = [student1, student2, student3]
for student in students:
print(student.gp)

how assign list attributes to a class python 3 [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I need to create a class student and then assign him or her a subject (maths, science, etc.) and then the grade by subject.
Basically, I have created a class student with name, gender,etc. Then I need to add more than one subject.
But i dont understand how one student object can get more than one subject and probably a greade per subject.
class student:
def __init__(self,name,age,gender,subject):
self.name = name
self.age = age
self.gender = gender
self.subject = subject
def __str__(self):
return ('{},{},{},{}'.format(self.name,self.age,self.gender,self.subject))
new = student('Alan',17,'M','Science')
Please if someone can help me to clarify a little bit I appreciate.
thanks
From your question, I gather that you have already worked with entity relations (ERDs), which is why you are thinking in terms of associations -- which is good. I'm assuming this is homework, so I don't want to give away too much. However, the code below should get you started.
from typing import List, Dict
class CollegeClass:
def __init__(self, class_code: str, name: str):
self.class_code = class_code #type: str
self.name = name
def __str__(self):
return f"{self.class_code}, {self.name}"
def __repr__(self):
return str(self)
class Student:
def __init__(self):
self.current_classes = dict() # type: Dict[str, CollegeClass]
def enroll(self, college_class: CollegeClass):
if college_class.class_code in self.current_classes:
print("The student is already taking the class.")
return
self.current_classes[college_class.class_code] = college_class
if __name__ == '__main__':
math = CollegeClass("mth101", "Intro to Math")
english = CollegeClass("eng201", "Intro to Fiction")
eric_praline = Student()
eric_praline.enroll(math)
eric_praline.enroll(english)
for _, cls in eric_praline.current_classes.items():
print(cls)
There are many ways to accomplish this task. One solution is to not specify the subject when creating the student. Instead, you would create the student object and then add subjects to it.
For example:
student = Student(name="John Smith")
for subject_name in ("Math", "Science", "Literature"):
student.add_subject(subject_name)
That gives you a new student who has three subjects. The add_subject method might look something like this:
class Student(object):
def __init__(self, name, age, gender):
...
self.subjects = {}
...
def add_subject(self, name):
self.subjects[name] = Subject(name)
To assign grades you would do something like this, perhaps
student.add_grade("Math", "A")
student.add_grade("Science", "B")
student.add_grade("Literature", "C")
add_grade would then take the grade name, look up the subject object from self.subjects, and call a method on that subject object to add the grade.
For example:
def add_grade(self, subject_name, grade):
subject = self.subjects[subject_name]
subject.add_grade(grade)
Your class Subject could be something very simple:
class Subject(self):
def __init__(self, name):
self.name = name
self.grade = None
def add_grade(self, grade):
self.grade = grade
Note: the above assumes you want a single grade per subject. If you want multiple grades, you can change self.grade to be self.grades and have it be a list.
Class Student represents just a type of people
Object of class Student represents a particular student, e.g. John Smith
Class Subject represents something students can learn in general
Object of class Subject represents a particular class students can take, e.g. Math 2017
Grade does not belong in either of these, because it only makes sense with a combination of both. So I would suggest creating some data storage, e.g. a list of tuples to store a grade for each combination of student/subject objects you want to keep track of, e.g.
Grades = [
(john_smith, math_2017, 'A+'),
...
]
class Subject(object):
def __init__(self, name, grade=None):
self.name = name
self.grade = grade
class student:
def __init__(self,name,age,gender, subjects=[]):
self.name = name
self.age = age
self.gender = gender
self.subjects = {}
for sub in subjects:
self.subjects[sub] = Subject(sub)
# Create new student with 2 subjects (Art and Science)
new = student('Alan',17,'M', subjects=['Art', 'Science'])
# You can wrap the following processes in functions if so desired
# Add a new subject later on (Math)
new.subjects['Math'] = Subject('Math')
# Add grades
new.subjects['Art'].grade = 'C'
new.subjects['Science'].grade = 'A+'
new.subjects['Math'].grade = 'B-'
# Get a list of subjects and grades
print([(sub.name, sub.grade) for _, sub in new.subjects.items()])
>>>[('Art', 'C'), ('Science', 'A+'), ('Math', 'B-')]
But i [don't] understand how one student object can get more than one subject and probably a [grade] per subject.
Pass in a dictionary of {subject: grade} pairs.
Code
class Student:
def __init__(self, name, age, gender, subjects=None):
self.name = name
self.age = age
self.gender = gender
# Handle mutable keyword defaults
if subjects is None:
self.subjects = {}
else:
self.subjects = subjects
def __repr__(self):
return ("{0.name}, {0.age}, {0.gender}, {0.subjects}".format(self))
subjects = {"Math": "A", "Biology": "B-", "Chemistry": "A"}
s = Student("Joe", 20, "M", subjects=subjects)
s
# Joe, 20, M, {'Math': 'A', 'Chemistry': 'A', 'Biology': 'B-'}
s.subjects["Math"]
# 'A'
Assigning None to a keyword argument is a convention for avoiding a well-known gotcha when assigning mutable arguments, e.g. lists, dictionaries. The lines that handle subjects is equivalent to this one-liner:
self.subjects = {} if subjects is None else subjects
The __repr__() method was defined, which you may wish to include along with __str__().

How to create and set variables as classes from a list of tuples?

I am trying to figure out how to create variables from a list of tuple and assign them to a class.
I have data organized like this
Name Age Status
John 30 Employed
That I have created a list of tuple like this
employeelist = [(John, 30, Employed), (Steve, 25, Part-Time)]
And a class set up like this
class Employee():
ecount = 0
elist = []
def __init__(self, name, age, emp_status):
self.name = name
self.age = age
self.emp_status = emp_status
self.lookup = {}
Employee.ecount = Employee.ecount+1
Employee.elist.append(self.name)
Using this code I am able to turn the tuple into an instance of the class
for i in range(0, len(employeelist),1):
sublist = [str(n) for n in employeelist[i]]
Employee(sublist[0], sublist[1], sublist[2])
But I am not able to access them. Is there a way to think about setting up the for loop to create a variable from sublist[0] and then create a class out of it (e.g. sublist[0] = Employee(sublist[0], sublist[1], sublist[2]))?
You just need
employees = [Employee(*v) for v in employee_list]
Note that employees and Employee.elist are essentially the same once
each Employee object has been created.

How do i store multiple object attibutes to a single dictionary key?

I'm fairly new to the world of python and programming in general, and its rare that i get up the nerve to ask questions, but I'm stomped so i thought id suck it up and ask for help.
I'm making an Address book.
class Person():
def __init__(self,name,number,email):
self.name = name
self.number = number
self.email = email
contact = Person('Mike','1-800-foo-spam','email#email.com')
My question is how would go about storing all these attributes in a dictionary with contact.name as the key and contact.number and contact.email as the values.
Bonus question.
Should the dictionary be outside the class, perhaps in the main function?
or
Does it need to be a class variable(not completely sure how those work)
or an object variable
something like
self.storage = {}
Any help would be greatly appreciated.
Thank you!
If I put this information in a dictionary, I would do it like that:
class Person():
def __init__(self,name,number,email):
self.name = name
self.number = number
self.email = email
self.storage = {self.name: [self.number, self.email]}
def getStorage(self):
return self.storage
contact = Person('Mike','1-800-foo-spam','email#email.com')
print contact.storage
# or
print contact.getStorage()
But the whole idea of a dictionary is to have a number of keys and corresponding values. In this example, it always will be one only. So, another schema comes to my mind:
class Person():
def __init__(self,name,number,email):
self.name = name
self.number = number
self.email = email
# creating some example contacts
c1 = Person('Mike','1-800-foo-spam','email#email.com')
c2 = Person('Jim','1-700-foo-spam','e111mail#email.com')
c3 = Person('Kim','1-600-foo-spam','e222mail#email.com')
# creating a dictionary to fill it with c1..cn contacts
contacts = {}
# helper function to automate dictionary filling
def contactToDict(list_of_contacts):
for item in list_of_contacts:
contacts[item.name] = (item.number, item.email)
contactToDict([c1, c2, c3])
"""
expected output:
Mike: ('1-800-foo-spam', 'email#email.com')
Jim: ('1-700-foo-spam', 'e111mail#email.com')
Kim: ('1-600-foo-spam', 'e222mail#email.com')
"""
for key, val in contacts.items():
print str(key) + ": " + str(val)
The answer to the title of the question: a value should be a type of object with allows to have a "list" inside (i.e. list, tuple, another dictionary or custom type object having a number of attributes.)
You can pretty easily have a dictionary with tuples as the values.
a = {}
a["bob"] = ("1-800-whatever","bob#gmail.com")
If you wanted to make it a class variable, you'd just need to create an empty dictionary as part of the Person class:
class Person():
storage = {}
Then in __init__ you can store the new person's info in that dictionary:
def __init__(self,name,number,email):
self.name = name
self.number = number
self.email = email
Person.storage[name] = (number, email)
As you can see class attributes are accessed with the classname, but otherwise like any other attribute. You could store them as a tuple or a list if you need to update them. However if you intend to make changes, it might be better to store the actual Person object, to save having to update Person.storage and the actual person at the same time. This is even easier to do:
def __init__(self,name,number,email):
self.name = name
self.number = number
self.email = email
Person.storage[name] = self
self refers to the instance of Person that's being created with __init__. That's Mike in your example. Then you could access their values by attribute:
Person.storage["Mike"].number
Also as Kevin pointed out in a comment you might want to detect if the key already exists to avoid overwriting an old entry (eg. if there's already a Mike in the dictionary):
self.email = email
if name in Person.storage:
# Make unique name
Person.storage[name] = (number, email)

Python list to store class instance?

Given a python class class Student(): and a list names = []; then I want to create several instances of Student() and add them into the list names,
names = [] # For storing the student instances
class Student():
def __init__(self, score, gender):
self.score = score
self.gender = gender
And now I want to check out the scores of all the male students, can I do it like this?
scores = []
for i in names:
if i.gender == "Male":
scores.append(i.score)
My question is: How to create a list that can (if could be done by any statement) store the instance of Student? Or rather, when I write names = [], how could I state every element in names is an instance of Student so that I can use the attributs of this element despite python is weak type? I hope I made myself clear ;)
Can I write like:
for i in range(len(names)):
student = Student()
student = names[i]
if student.gender == "Male":
# Whatever
I guess not...
Did you try your code above? It should work fine. You can condense it into:
scores = [ student.name for student in names if student.gender == "Male" ]
Note that calling the list names is misleading, since it is a list of Student instances.
You can't define the list to be a list of Student instances; that's not how Python works.
Are you asking how to create the list that you've called names?
names = [ ]
for ( score, gender ) in <some-data-source>:
names.append( Student( score, gender ) )
which is of course equivalent to
names = [ Student( score, gender ) for score, gender in <some-data-source> ]
and in turn to
names = [ Student( *row ) for row in <some-data-source> ]
If you need to do a lot of processing for each row then you can either move the processing into a separate function or use a for loop.
def process_row( row ):
...
return score, gender
names = [ Student( *process_row( row ) ) for row in <some-data-source> ]
Responding to your edit, I think you are trying to declare the types of variables in Python. You wrote:
for i in range(len(names)):
student = Student()
student = names[i]
if student.gender == "Male":
# Whatever
What is the purpose of the line student = Student() -- are you trying to declare the type of the variable student? Don't do that. The following will do what you intended:
for student in students:
if student.gender == "Male":
# Whatever
Notice several things:
We don't need to iterate over range(n) and then look up each instance in names; iterating over every element of a container is the purpose of a for loop.
You don't need to make any claims about what student is -- it could be a string, a boolean, a list, a Student, whatever. This is dynamic typing. Likewise, students doesn't have to be a list; you can iterate over any iterable.
When you write student.gender, Python will get the gender attribute of student, or raise an exception if it doesn't have one.
First of all python is not weakly typed. It is however dynamically typed so you can't specify an element type for your list.
However this does not prevent you from accessing an object's attributes. This works just fine:
names = [Student(1,"Male"), Student(2,"Female")]
scores = []
for i in names:
if i.gender == "Male":
scores.append(i.score)
It is however more pythonic to write this using a list comprehension:
names = [Student(1,"Male"), Student(2,"Female")]
scores = [i.score for i in names if i.gender == "Male"]
I'm fairly new to OOP, but does this not do what you want quite nicely? name_list is a class variable, and every time you create a new Student object, it gets added to Student.name_list. Say for example you had a method cheat(self) which you wanted to perform on the third student, you could run Student.name_list[2].cheat(). Code:
class Student():
name_list = []
def __init__(self, score, gender):
Student.name_list.append(self)
self.score = score
self.gender = gender
#this is just for output formatting
def __str__(self):
return "Score: {} || Gender: {}".format(self.score, self.gender)
#again for output formatting
def update(): print([str(student) for student in Student.name_list])
update()
Student(42, "female")
update()
Student(23, "male")
update()
Student(63, "male")
Student(763, "female")
Student("over 9000", "neutral")
update()
Output:
[]
['Score: 42 || Gender: female']
['Score: 42 || Gender: female', 'Score: 23 || Gender: male']
['Score: 42 || Gender: female', 'Score: 23 || Gender: male', 'Score: 63 || Gender: male', 'Score: 763 || Gender: female', 'Score: over 9000 || Gender: neutral']

Categories

Resources