0

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

Andres Urrego Angel
  • 1,842
  • 7
  • 29
  • 55
  • Your explanation is a little confusing. Do you have some code that would illustrate what you want to do? – Patrick Haugh Jan 11 '18 at 16:33
  • You don't assign one class to the other, the student object will have a subject *object* as a property. This could be done in the `__init__()` for the student and/or in a student object method. – cdarke Jan 11 '18 at 16:35
  • @cdarke I follow you, then I dont need a class for subjects, you said just added as an attribut but then if the same student has 10 subjects and I just have one attribute subjects how the objects student will catch 10 times the attribute subject? that is what confuse to me. thanks – Andres Urrego Angel Jan 11 '18 at 16:37
  • just use a list of subjects, initialise it as `[ ]` and `append` each one as it is added. – cdarke Jan 11 '18 at 16:43
  • I think your original question title was better than the one you changed it to in revision 4. – Bryan Oakley Jan 11 '18 at 16:52

5 Answers5

1

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.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
1

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)
SteveJ
  • 3,034
  • 2
  • 27
  • 47
  • I failed to address grading -- of which there are many ways. A simple solution is to have a dictionary whose key is the class_code, and whose value is either the letter grade, or even another class that holds information about how the student did in the class (grade, attendance, scores, etc). I can edit the answer to elaborate if you need. – SteveJ Jan 11 '18 at 18:22
0

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+'),
    ...    
]
CrowbarKZ
  • 1,203
  • 11
  • 18
0
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-')]
noslenkwah
  • 1,702
  • 1
  • 17
  • 26
0

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

pylang
  • 40,867
  • 14
  • 129
  • 121