FAQ: Learn Python: Inheritance and Polymorphism - Review


#1

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!


#2

Hi, I just finished the section on polymorphism, and here is what I came up with in order to make the SortedList to be sorted at initialization (spoilers, if you want to solve this bonus yourself, don’t look):

Code
class SortedList(list):
  def __init__(self, values):
    super().__init__(self)
    self.values = values
    self.values.sort()
  
  def append(self, value):
    super().append(value)
    self.sort()

  def __repr__(self):
    return str(self.values)

a = SortedList([3, 45, 1234, 21])

print(a)

And it works, but it seems that it forces me to keep the values outside of the parent class, that is, it seems I can’t make the super().__init__() function initialize the values I receive for me, I tried passing them directly to it, but it said that it only accepts one argument: self.

And this of course then forces me to overwrite __repr__(), because otherwise when I try to print my SortedList it prints an empty list (since the values are not accessible from the parent class).

So I would just like to know if there’s something I’m doing wrong/not optimized or if it’s how it’s supposed to work? In a way it would also make sense to work like that, because otherwise I don’t know how you would access the values in the subclass (maybe from a return from super() ?)

Thanks to anyone who takes the time to answer me.


#3

H, @arjofocolovi. This my personal opinion and I’m no professional expert. I think your code does not exactly correspond to what the exercise asks for, which is that SortedList should be a child class implementation of List. This means that the sorted list is the class object itself. But in your case, the sorted list is the not the class object itself, but rather an instance variable defined inside the class, of type list and named values.

Anyway, here is my code. Hope it is what the exercise requires and hope it helps you.

My Code
class SortedList(list):
  
  def __init__(self, lst):
    super().__init__(lst)
    self.sort()
  
  def append(self, value):
    super().append(value)
    self.sort()
 

new_list = SortedList([4, 1, 5])
print(new_list)
new_list.append(0)
print(new_list)


#4

Indeed, I discovered that later on during the last project, my mistake was to try to pass self when calling super() on __init__, which you shouldn’t do, otherwise you run out of arguments (and you don’t even give the proper arguments anyway). But thanks for your answer, I forgot to update this thread.


#5

Hi, I have a question about the end of the polymorphism section (Review). I don’t understand why we have to call super() to apply append() method on our object SortedList but we don’t have to do it when we apply sort() method in the next line:

class SortedList(list):

  def append(self, value): 
    super().append(value) 
    self.sort()

Is it because we apply super().append(value) before and SortedList already behaves like a list?

Thanks for helping me!


#6

In this case it doesn’t change much because we have not overwritten sort() in any way, so calling self.sort() will simply use the default sort() which we inherited from the list class, so using super() or not wouldn’t matter.

However, if we had modified sort(), then there could be a significant difference between calling self.sort(), that is, calling the sort() from our LinkedList class, and calling the original sort() from the list class.


#7

Thank you so much for your explanation, I didn’t think about the fact we were overwriting the append() method but not sort(), I understand now :slight_smile:


#8

For the record, overridden is not synonymous with overwritten. We are not overwriting a parent method, but overriding it.


#9

What is the difference between the two in Python?


#10

I dont’ know that Python has a term, overwrite which means simply to replace some text with some other text. Override on the other hand means ‘to prevail over’ or ‘supersede’. The parent class method is ‘set aside’ in favor of the derived class method.


#11

But aren’t we replacing text with some other text given that we’re modifying the behavior of a method when we’re overriding it? I mean, we’re literally rewriting the method, so I don’t know, seems pretty similar in this context.
But thanks for the correction, if that’s simply the terminology used I guess it’s more useful to use it, I hope it’ll stick into my memory.


#12

No, the overriding method is not replacement text, but the same of similar text by the same variable name in another class. It’s the existence of that other method in the subclass that permits it to override the parent.

For our own sake, we should firm up what terminology to use in any situation. It’s hard enough to learn the language, as it is. We don’t want to muddle ourselves into a bent way of thinking.


#13

Hello guys !
I’m new to programming and im struggling with classes right now. I’m trying to solve another task from this topic. To be exact:

" What other Python builtins have functionality “missing”? Could you write a new dictionary that uses a fallback value when it tries to retrieve an item and can’t?"

I tried to solved it by myself but it’s too hard for me :frowning: Here’s my code(it’s not working):

class SuperDict(dict):
  fallback_value = "There is no such a key"
  def __init__(self, dic):
    super().__init__(dic)
    self.dic = dic
  def __getitem__(self, key):
    super().__getitem__(key)
    try:
      self.dic[key]
    except KeyError:
      return print(fallback_value)


d = SuperDict({"k": 10, "b": 5})

print(d["c"])

Could someone take a look at this and try to explain to me what’s my mistakes are ? Thanks for help in advance.
PS I’m not english speaking person, so sorry for my english.

Regards,
Daniel.


#14

I need help with that one too. I’m not entirely sure what they mean by a “new dictionary that uses a fallback value”. Doesn’t every dictionary have the .get() method by default? What are they expecting us to write?


#15

I have tried modifying your code a bit to make it work.

class SuperDict(dict):
  fallback_value = "There is no such a key"
  def __init__(self, dic):
    super().__init__(dic)
    self.dic = dic
  def get(self, key):
    super().get(key)
    try:
      return self.dic[key]
    except KeyError:
      return self.fallback_value


d = SuperDict({"k": 10, "b": 5})

print(d.get("c"))

I think the main issue is dunder method are specific for certain operators and may not be applicable to .get() build in method of the list class. I’ve edited getitem to be a regular method and it appears to work for tests I’ve conducted. Though I suspect the extra exercise actual instruction may be to modify the .get() method of the list class to return a fallback value instead of creating a new method for it.