FAQ: Learn Python: Inheritance and Polymorphism - Review

This community-built FAQ covers the “Review” exercise from the lesson “Learn Python: Inheritance and Polymorphism”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Computer Science

FAQs on the exercise Review

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

3 posts were split to a new topic: Bonus Challenge Discussion

8 posts were split to a new topic: When do I need to use super()?

13 posts were merged into an existing topic: Bonus Challenge Discussion

A post was merged into an existing topic: Bonus Challenge Discussion

5 posts were split to a new topic: Fixing my code

6 posts were merged into an existing topic: When do I need to use super()?

A post was merged into an existing topic: When do I need to use super()?

8 posts were split to a new topic: Where are the built in functions in python?

How can I file a bug for this content? I was banging my head at step 2 of this which states:

" Recall that lists have a .append() method that takes a two arguments, self and value . We’re going to have SortedList perform a sort after every .append() .

Overwrite the append method, leave it blank for now with the pass keyword."

I kept trying to submit the following code:

class SortedList(list):
def append(self,value):
pass

and it kept failing…over…and OVER. I finally found out the issue…a missing space after the comma in the parameters:

class SortedList(list):
def append(self, value):
pass

This code passed! Functionally, from a Python POV, they are the EXACT same code. This needs to be fixed…random formatting issues like this are one of my biggest pet peeves of Codecademy!

4 Likes

You can select the Get Help option on the lower right of the lesson. There is a bug report option.

1 Like

I expected to have to perpend the last line of my append method override, as shown below:

class SortedList(list):
  def append(self, value):
    super().append(value)
    return self.sort()

This, however, does not seem to be the case… can someone please explain why this is?

When treated as a statement, this will sort an iterable in-place. That means everything is done ON the list.

When treated as an expression, it has no value, so return will be None. No matter; a return isn’t expected anyway. append is itself an action that takes place ON the list, also with no return value.

In short, return is not needed. There is nothing to return if all the operations have been done on the object. It is in a completely new state.

The only reason for having an append method on this class is to extend what append does in the case of a SortedList instance. It not only appends, but it also sorts after appending. We still need the built-in inherited from the super to give us the appended list which we then sort in-place with the method inherited from list.

It actually makes sense to have an extend method, in addition to append so we can start with an empty list, and build it in a single step, later.

def extend(self, other):
    super().extend(other)
    self.sort()

a = SortedList([])
a.extend([8,6,7,5,6,8,9,4,5,3,4,5,6,7,2,1,9])
print (a)
[1, 2, 3, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9]
1 Like

How can I find out the names of the method’s parameters in order to modify them?

For example, in the lesson review to modify the “append” method, I needed to know that it’s defined in the parent class using the parameters “self” and “value”. This information was given in the exercise. However, with some methods I might not know what parameter names Python uses. How can I find these out, in order to modify them?

Thanks!

The simplest and likely best way is to read the documentation at python.org or its wiki and other reliable sources. Once you learn how to read the specs it becomes relatively simple to get up to speed with any new concept, construct, function, etc. Keep the docs close at hand and refer to them often. That’s what we all do, still, even after years.

The built-in list.append() method takes an object (value) and adds it to the right end of the list. It doesn’t need a self parameter since self in this case is the list we are appending. All it needs is a value. There is only one positional argument for this method.

>>> a = []
>>> a.append(1,2,3,4)
Traceback (most recent call last):
  File "<pyshell#145>", line 1, in <module>
    a.append(1,2,3,4)
TypeError: append() takes exactly one argument (4 given)
>>> 

We would need to use a different built-in, or run this method four times to append all those values. The other method is list.extend() which may come up in your reading of list methods. Note below their subtle difference…

>>> a = []
>>> a.append(1,2,3,4)
Traceback (most recent call last):
  File "<pyshell#152>", line 1, in <module>
    a.append(1,2,3,4)
TypeError: append() takes exactly one argument (4 given)
>>> a.append([1,2,3,4])
>>> a
[[1, 2, 3, 4]]
>>> a = []
>>> a.extend(1,2,3,4)
Traceback (most recent call last):
  File "<pyshell#156>", line 1, in <module>
    a.extend(1,2,3,4)
TypeError: extend() takes exactly one argument (4 given)
>>> a.extend([1,2,3,4])
>>> a
[1, 2, 3, 4]
>>> 

Again, only one positional argument but note how the append method treats the sequence compared to the extend method.

Above we mentioned that self is the list object in context. It always refers to the instance object that is invoking the method. In classes we will always have self as an argument if the function is accessing any variables, instance or class. Likewise when one method calls another, the other method is also, self.method().

Thank you for the response! It made it clear to me that my question was based on a misunderstanding.

The exercise was about changing the built in or dunder methods of basic python classes in sub classes created from them. Based on the exercise, and without having experimented, I thought that I could only modify a parent-class method in a sub-class, if I defined it in the sub-class using the same names for the parameters (or exactly the same way as it was defined in the parent class).

In other words I thought that the code below would only allow me to create a modified sub class of lists, if I defined the init and append methods by using (self, value) and (self, values) in brackets respectively.

class SortedList(list):
def init(self, values):
super().init(values)
self.sort()
def append(self, value):
super().append(value)
self.sort()

However, after having experimented, I noticed that that’s not the case. The sub class methods work regardless of what names I give to the parameters. I.e. the code below also works the exact same way:

class SortedList(list):
def init(self, a):
super().init(a)
self.sort()
def append(self, b):
super().append(b)
self.sort()

Thanks again for getting me to think more about my question and have a great day!

1 Like

You’re welcome! If you are content with creating an empty SortedList instance, you don’t have to initialize anything.

a = SortedList()

a will be []

Now run the append method on that instance.

a.append(9)
a.append(19)
a.append(3)

Now when you print a you get, [3, 9, 19]. Give this a try (without the __init__() method in your subclass).

hello! much love and appreciation to you guys! thanks for creating this platform!

a few suggestions on this section :

-this sections was far too advanced and used the python jargon flawlessly, however, it was hard to understand. maybe if micro repetitions of the jargon (little by little, one by one) could be performed rather than condensing 3-4 freshly learned jargon oriented words into one piece, maybe that would help us newbies understand better.

-secondly, i would suggest making this section much longer in order for each subject/word to be understood and grasped to the best extent. the condensation, again, seems very advance to the untrained eye.

-other than that, it was entertaining, engaging, and fun! thank you.

I’m working on the bonus question, when I run:

lass SortedList(list):
  def __init__(self):
    self.sort()
  def append(self, value):
    super().append(value)
    self.sort()
    
names =  SortedList(['billy','bobby','jimmy','alfred'])
#bobby.append('AL')
print(names)

I get the error:

Traceback (most recent call last):
  File "script.py", line 9, in <module>
    names =  SortedList(['billy','bobby','jimmy','alfred'])
TypeError: __init__() takes 1 positional argument but 2 were given

I’ve figured out that i need a second argument in my __init__constructor:

def __init__(self,_list):
    _list.sort()

However I don’t understand why just having self in my init doesn’t work.

class SortedList(list):
def append(self, value):
super().append(value)
self.sort()

list_1 = SortedList([3,2,5,6])
print(list_1)

#This prints None
lst = list_1.append(8)
print(lst)

#This prints the sorted list
list_1.append(8)
print(list_1)

Hi All, still trying to understand this. Why does one prints the sorted list and the other doesn’t in the code above? Still a beginner here and would like to understand this topic a bit further as I’m finding it hard to understand sometimes.