SortedList Exercise - Sorting on initialisation

HI Folks

So i just completed the Inheritance and polymorphism section in the the CS path.

I’m missing one thing, which is the missing link to me fully understanding this.

I have the following code

class SortedList(list):

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

m_list = SortedList([4,1,5])
print(m_list)

i now want to adopt it so that when i initialise the instance the list gets sorted straight away.
I have tried a number of things but cant seem to get it to work.

Any suggestions to guide me as to what i am missing?

cheers

self is not something we would sort.

Please post a link to this exercise.

@mtf - here is the link:

https://www.codecademy.com/paths/computer-science/tracks/cspath-python-objects/modules/cspath-python-classes/lessons/inheritance-and-polymorphism/exercises/review-concepts

Okay, turns out I was wrong in my last statement. self is the inherited list object.

As for how to sort the instance I’m at an impasse. The lesson is positively vague. Maybe @appylpye can shed some light on this.

The following was tested with Python 3:

class SortedList(list):
  def append(self, value):
    super().append(value)
    self.sort()
   
a_sorted_list = SortedList([5, 9, 7, 3])

a_sorted_list.append(4)
print(a_sorted_list)

Output:

[3, 4, 5, 7, 9]

Within the append method included above, the super built in function knows to apply the append method of list, the superclass, to the current instance of SortedList.

Then, referring to the current instance as self, we can call from it the sort method that is inherited from list.

Note that we really ought to write an __init__ method for the SortedList class, so that we can put it in sorted condition right from the start. Step 5 does hint at the need for this, and @ byterockstar71616 does ask about this issue.

This statement, placed in the __init__ method, should take care of that:

    self.sort()

The question here is how does one do it without including a constructor?

If you do not include a constructor, wouldn’t you then always begin with an empty SortedList object?

1 Like

When I add the constructor the SortedList object is empty.

class SortedList(list):
  def __init__(self, values):
    self.values = sorted(values)
  def append(self, value):
    super().append(value)
    self.sort()
    
a = SortedList([4, 1, 5])
print (a)
a.append(2)
print (a)

Output

[]
[2]

The print function doesn’t know that it should look at the values instance variable, and the append method of SortedList doesn’t know that it should add the supplied argument to that instance variable either.

We could do it this way:

class SortedList(list):
  def __init__(self, a_list):
    for item in a_list:
      self.append(item)
    self.sort()
  def append(self, value):
    super().append(value)
    self.sort()
1 Like
class SortedList(list):
  def __init__(self, values):
    self.values = sorted(values)
  def append(self, value):
    super().append(value)
    self.sort()
    
a = SortedList([4, 1, 5])
print (a.values)
a.append(2)
print (a.values)
[1, 4, 5]
[1, 4, 5]

Obviously we cannot construct self else the append method doesn’t work. Trying your suggestion…

I was worried that the initial list would be extended, but it appears it is only overwritten with the same values.

[1, 4, 5]
[1, 2, 4, 5]

Thanks for chiming in, @appylpye.

1 Like

If you would like to continue with the values instance variable, the following will work, with no need to call the super function:

class SortedList(list):
  def __init__(self, values):
    self.values = sorted(values)
  def append(self, value):
    # replace the following with a more efficient insertion
    self.values.append(value)
    self.values.sort()
  def __repr__(self):
    return str(self.values)
    
a_sorted_list = SortedList([5, 9, 7, 3])
print(a_sorted_list)
a_sorted_list.append(4)
print(a_sorted_list)

Output:

[3, 5, 7, 9]
[3, 4, 5, 7, 9]

Would we even need to inherit from list if this were the case?

1 Like

With this approach, the inheritance would no longer be useful; it is just a relict of the fact that this was part of a lesson in inheritance and polymorphism.

1 Like

On second thought, the inheritance would be useful for identifying an instance of a SortedList as a type of list. This is so that the user of a SortedList could selectively exploit behaviors that are expected with list objects, such as the ability of the len function to offer a meaningful measure of the size of the object. See the discussion How do I make len() work with my class?.

In the following, we select only instances of list objects as arguments to pass to the len function, and these include instances of SortedList:

class SortedList(list):
  def __init__(self, values):
    self.values = sorted(values)
  def append(self, value):
    self.values.append(value)
    self.values.sort()
  def __repr__(self):
      return str(self.values)
  def __len__(self):
      return len(self.values)

list_of_wannabe_lists = [[1, 2, 3],
                         SortedList([9, 7, 11]),
                         144,
                         SortedList([7, 2])
                        ]

for item in list_of_wannabe_lists:
  if isinstance(item, list):
    print(len(item))
  else:
    print("non-list encountered")

Output:

3
3
non-list encountered
2

A note of caution is in order here. In the above, we implemented use of the len function, but real list objects can also be sliced. There are also various list methods that users of SortedList objects might elect to call. If we are to enable SortedList instances to function as bona fide list instances, we would need to implement all of that functionality.

1 Like

Wow guys, thank you all for chiming in!!

In the end i think the interpretation of that exercise i went for the self.values = sorted(values) in the constructor.

I was under some impression that i could return the sorted list without declaring it in an object, but like was put earlier, you just get an empty list.

But what a great discussion to see many of the things i tried put here… i thought i was loosing the plot or not getting it.

2 Likes