1

I'm new to Python object oriented programming. I copied this code online to get a better sense of how OOP worked in Python. Here is the code:

class Student:

    def __init__(self, name, student_number):
        ## Student has-a name
        self.name = name
        ## Student has-a student number
        self.student_number = student_number
        ## Student has-many classes
        self.classes = []

    def enrol(self, course_running):
        ## Append the list, classes with variable course_running
        self.classes.append(course_running)
        ## Call course_running with the add_student function in a class
        course_running.add_student(self)

class Department:

    def __init__(self, name, department_code):
        ## Department has-a name
        self.name = name
        ## Department has-a code
        self.department_code = department_code
        ## Department has-many courses
        self.courses = {}

    def add_course(self, description, course_code, credits):
        self.courses[course_code] = Course(self, description, course_code, credits)
        return self.courses[course_code]

class Course:

    def __init__(self, description, course_code, credits, department):
        ## Course has-a description
        self.description = description
        ## Course has-a code
        self.course_code = course_code
        ## Course has-many credits
        self.credits = credits
        ## Course has-a deparmtnet
        self.department = department
        ## Adds the aforementioned course to the necessary DPT; it is usefull because
        ## it automatically adds this course to the DPT given in its parameter
        self.department.add_course(self)
        ## Course has-many runnings
        self.runnings = []

        def add_running(self, year):
            self.runnings.append(CourseRunning(self, year))
            return self.runnings[-1]

class CourseRunning:

    def __init__(self, course, year):
        ## CourseRunning has-a year
        self.course = course
        ## CourseRunning has-a year
        self.year = year
        ## CourseRunning has-many students
        self.students = []

    def add_student(self, student):
        self.students.append(student)

maths_dept = Department("Mathematics and Applied Mathemtics", "MAM")
mam1000w = maths_dept.add_course("Mathematics 1000", "MAM1000W", 1)
mam1000w_2013 = mam1000w.add_running(2013)

bob = Student("Bob", "Smith")
bob.enrol(mam1000w_2013)

However, I keep getting these errors:

Traceback (most recent call last):
  File "ex42c.py", line 70, in <module>
    mam1000w = maths_dept.add_course("Mathematics 1000", "MAM1000W", 1)
  File "ex42c.py", line 30, in add_course
    self.courses[course_code] = Course(self, description, course_code, credits)
  File "ex42c.py", line 47, in __init__
    self.department.add_course(self)
AttributeError: 'int' object has no attribute 'add_course'

I changed the 'int' object into a 'list' object then a 'str' object, but they produced similar errors. When I deleted the integer and all 'credit' variables, the same error occurred with the 'course_code' variables and with str "MAM1000W." Basically, I want to understand why I cannot pass these parameters to the function.

Thanks in advance.

2
  • 1
    There seems to be several errors in how you create your objects. Course for example needs department last but you pass it first in the add_course method of departments. Also the constructor of Course calls add_course again. Apart from not passing the correct parameters this seems to be an infinite loop for me. Commented Jan 7, 2020 at 9:11
  • " I copied this code online to get a better sense of how OOP worked in Python" => well, I don't know where you copied this from, but if it's a verbatim copy-paste then you want to find a better "resource" to learn things from. Commented Jan 8, 2020 at 16:48

2 Answers 2

1

The first issue is that you're passing the arguments to Course in the wrong order.

Instead of self.courses[course_code] = Course(self, description, course_code, credits)

You need self.courses[course_code] = Course(description, course_code, credits, self)

Because in your Course.__init__ you have them in that order: def __init__(self, description, course_code, credits, department).

But then you have a recursive loop where the add_course function is called by the Course __init__, which is called when you create a Course in add_course... and so on and so forth.

Except that wouldn't happen either, because your call to self.department.add_course(self) in the Course.__init__ is missing two required arguments for Department.add_course - course_code and credits

In short: you have a lot of problems here. We could fix most of them, but the decision about the recursive call to add_course is going to require you to decide whether you want a department to add courses, or courses to add themselves to departments.

Sign up to request clarification or add additional context in comments.

Comments

1

Delete this

After deleting the above ( self.department.add_course(self)) please unindent the part below :

def add_running(self, year):
    self.runnings.append(CourseRunning(self, year))
    return self.runnings[-1]

It works for me although I am not sure if this is the way you wanted it to work.

It previously did not work because you tried to use Department's method from within Course class. The department was just an argument of Integer type instead of the Department object you probably wanted. The same method is already there in Department class so why not use it only?

The second part was unindenting the add_running() function as it was typed within the init block of Course.

I hope that helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.