What is self in a Python class?
self is the object the method was called on. When you write ana.average(), Python runs Student.average(ana), so inside the method self is ana and self.marks is Ana's list of marks. It is the first parameter of every method, supplied automatically by Python, and the word itself is only a convention, though one that every marker expects.
Why does print show something like Student object at 0x7f9c1d2b instead of my data?
Because the class has no __str__ method, so Python falls back on the class name and the memory address of the object. Write def __str__(self) that returns a string built from the attributes, for example the name followed by the average. It must return the string, not print it: print displays what __str__ returns, and a __str__ that prints crashes with a TypeError.
What is the difference between a class attribute and an instance attribute?
An instance attribute is written with self inside a method, usually __init__, and belongs to one object: each student has its own name and its own marks. A class attribute is written in the class body, outside every method, exists once and is shared by every object: a counter of objects created or a passing grade. Reading falls back from the object to the class, but assigning through self always creates the attribute on the object.
Why does == return False for two objects that have the same values?
Because without an __eq__ method, the equality sign compares identity: it asks whether the two names refer to the same object in memory, and two objects built by two calls to the constructor are two objects. Define def __eq__(self, other) and return the comparison of the attributes that make two objects equal, for example the seat number. The in operator on a list of objects uses the same rule.
When should I use inheritance rather than composition in COMP 202?
Use inheritance only when the sentence an X is a Y is true and every method of Y still makes sense on X: a savings account is an account, so deposit and withdraw apply to it. Use composition, an attribute that holds another object or a list of them, when X has a Y: a course has students. Sharing an attribute name such as name or average is never a reason to inherit.
What does super().__init__ do in a subclass?
It runs the parent's __init__ on the object being built, so that the attributes the parent declares, such as the owner and the balance of an account, exist on the child object too. Redefining __init__ in the child replaces the parent's version instead of extending it, so the call to super().__init__ with the parent's parameters must be the first line of the child's __init__, before the child adds its own attributes.