Codecademy Forums

FAQ: Learn Python: Inheritance and Polymorphism - Review

Only to see if it can be done.

Unlike in some languages, __init__ is not a constructor, as such since the object already exists, AND has a value, just not named.

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

		
>>> x = SortedList()
>>> x.extend([7, 4, 6, 1, -7])
>>> x
[-7, 1, 4, 6, 7]
>>> 

Wrap it in a function???

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

my_list = [4,1,5]

lst = SortedList(my_list)
print(lst)

lst.append(-25)
print(lst)

lst.append(3)
print(lst)

lst.extend([8,4,2,-1])
print(lst)

# Output:
[1, 4, 5]
[-25, 1, 4, 5]
[-25, 1, 3, 4, 5]
[-25, -1, 1, 2, 3, 4, 4, 5, 8]

Not pretty, but …

1 Like

A rather novel approach. I fear we may both be caught out for our naivete.

We may need to rustle up a curriculum advisor to lift the fog. @alyssavigil can you please scare one up to weigh in on this topic?

Thanks. Perhaps best to use a conventional initializer?

Sorry, I don’t have an answer as to what is best. There is a lesson here that we do not want to miss out on.

I don’t think ‘SuperDict’ needs a constructor. The structure of ‘SuperDict’ is essentially the same as the Python canonical class ‘dict’. I think you just need to override the Python get() method.

This code seems to work:

image

Thank you very much for all previous posts, I find them very helpful.
So, I have combined them into the following code, please suggest if we can make more improvements…

Special thanks to patrickd314, we updated:

class SortedList(list):

  def __init__(self, lst):
    super().__init__(lst)
    self.sort()

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

  def __str__(self):
    return '''__str__ is giving us more output control! 
Our output is: ''' + repr(self)
    
list_object = SortedList([4, 1, 5])
print(list_object)
# __str__ is giving us more output control!
# Our output is: [1, 4, 5]
list_object.append(2)
print(list_object)
# __str__ is giving us more output control!
# Our output is: [1, 2, 4, 5]
list_object.append(-1)
print(list_object)
# __str__ is giving us more output control!
# Our output is: [-1, 1, 2, 4, 5]

class SuperDict(dict):
    
  def __getitem__(self, key):
      try:
        return "The value for key {key} is {value}!".format(key = key, value = super().__getitem__(key)) 
      except KeyError:
        return "This key does not exist in this dictionary!"
    
dic = {i : i**2 for i in range(1, 6)}
super_dic_object = SuperDict(dic)
print(super_dic_object)
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
print(super_dic_object[2])
# The value for key 2 is 4!
print(super_dic_object[6])
# This key does not exist in this dictionary!
1 Like

It’s customary to put the __init__() method first; otherwise, :slightly_smiling_face: .

Also, we like to control the output of a call to print(obj) by means of a __repr__() or __str__() function:

  def __str__(self):   # or __repr__(self)
    output = ""
    for item in self:
        output += str(item)
    return output

(Just return self won’t work, as self is a SortedList object, not a string.)

1 Like

patrickd314,
I tried to implement your suggestions.
Could you review our changes please?

That part needs a slight edit of the quotes:

  def __str__(self):
    return '''__str__ is giving us more output control! 
Our output is: {}'''.format(repr(self))

Then, for the following calls:

my_list = SortedList([4,2,8,1,5])
my_list.append(-1)
print(my_list)

… you see this printed to the screen:

__str__ is giving us more output control! 
Our output is: [-1, 1, 2, 4, 5, 8]

Remember, that you can also override the behavior of repr() by means of __repr__(), the general idea being that __str__() is supposed to give you “pretty print” output for the benefit of your user, while __repr__() should contain more detailed, “under-the-hood” information for your benefit, as the developer.

The “string” output of repr() is simply Python’s default. You can make it what you want. You could have a list of all the appends, for example, if you needed it.

1 Like

Are you referring to repr()? Yes, that is the default behavior, to return a string representation of an object.

My point was that, if you create a class, then you have the ability (or even responsibility) to determine what a “string representation” of your object looks like.

1 Like