Bonus Challenge Discussion

Here could be the solutions:

5.1 “When a SortedList gets initialized with unsorted values (say if you call SortedList([4, 1, 5]) ) those values don’t get sorted! How would you change SortedList so that the list is sorted right after the object gets created?”

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

5.2 “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?”

class SuperFallback(dict):
  fallback_value = "There is no such key."
  def __init__(self, dic):
    super().__init__(dic)
    self.dic = dic
  def get(self, key):
    try:
      return self.dic[key]
    except KeyError:
      return self.fallback_value
d = SuperFallback({"a": [1, 2, 3], "b": [4, 5, 6]})
print(d.get("c"))
2 Likes

Didn’t see the notification of this when you posted it : /

list is a data structure, when you initialize it with an iterable value it will iterate through them and put a reference to each value in that structure

if it just kept a reference to the whole other iterable, then it wouldn’t be a data structure, there would be no structure, just a reference to something else, and, if you kept a reference to a list in your class there would be no point in inheriting list, you already have a reference to a list. is it a list, or does it have a list? pick one.

you need to call the parent __init__ because you’re not putting the values in that structure yourself (probably can’t access it directly anyway)
the parent class might also assume that its __init__ does get called, it’s a pretty reasonable assumption, so if you inherit something then your __init__, if you override it, should be calling the parent’s __init__

when it comes to the source code, much of the code you call from python (into C) is going to be about housekeeping. their code is quite nice and easy to understand so hey yeah you might just find what you’re looking for but it’s a lot more than just the thing itself and you might need to look in many places.

object creation isn’t done by __init__, __init__ happens once the object already exists, what you linked to is the function that creates a list object
__init__ is over here:
https://github.com/python/cpython/blob/b0461e19b5ecb2d89917b23efb5ce1048fab1b22/Objects/listobject.c#L2680
all it’s doing is calling list.extend. you could do this in your __init__ instead of calling the parent __init__, from what I can tell (which I don’t consider sufficient) this would be fine, but calling the parent __init__ is still the polite and correct thing to do

2 Likes

Ah that makes sense, thanks! It will definitely take some time getting used to the best practices and how to do and look for things.

Hi,
I also tried to complete this additional challenge.

My solution
class SortedList(list):
  def __init__(self, lst):
    super().__init__(lst)
    self.sort()

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

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

class MyDict(dict):
  def get(self, key, alt = ""):
      if super().get(key) == None:
        if alt == "":
          return "Error: key ({key}) not found.".format(key = key)
        else:
          return alt
      else: 
        return self[key]

  def keyOfValue(self, value):
    for key in self:
      print("key: ", key)
      if  self[key] == value:
        return key
    return "Error: value ({value}) not found.".format(value = value)

newDict = MyDict({
  "andi": "nice",
  "kriszta": "cute"
})

print(newDict)
print(newDict.get("béla"))
print(newDict.get("béla", "jani"))
print(newDict.keyOfValue("cute"))

MyDict is works but how can I create an error message instead of return a string? Or this solution is also good?
Because the original get() method returns None if the key is not exists (or any alternative value).
I also added a keyOfValue() method. It is return the key if the given value is exists in the dictionary, otherwise returns the same string (error) like my previous method.

Failure values need to be completely distinct from results. Same with your optional argument alt which can’t tell apart a default of empty string from missing default. And if you set a default, then it can’t ever be missing, can it? That’s what default means, that it’ll fall back to something and therefore always exist.

Neither of those methods are useful, dict already accomplishes … whatever that is, but that’s codecademy’s fault. It gets difficult to talk about what’s good when it isn’t useful.

class SortedList(list):

  def __init__(self, lis):

    self.lis = lis

    self.lis.sort()

  def append(self, value):

    self.lis.append(value)

    self.lis.sort()

s1 = SortedList([4, 1, 5])

s1.append(2)

print(s1.lis)

I have added a few functionality given in the bonus challenge, i did it without super() method. I still don’t under stand how it behaves.

like, does super() return anything?, how will I know what value I am passing in it? can I send my list variable lis in that method? will it make changes in this subclass?

please clarify.
Thanks,
Selva

1 Like

No, it does not return anything. The arguments are passed up to the parent class __init__() method.

Any instance variables of the parent that do not need to be overridden would be passed up from the subclass.

For this exercise, super() is used to invoke the parent object’s append method. We’re not actually passing anything to the parent.

1 Like

can I write a python program that overwrite “append” function?
I mean if I call .append(), no value will be added to the list.

We can override any method by defining our own class and writing that method inside that class. It will only act upon our instances, though.

It is likely possible to redefine a method on the built in list class but I doubt that is very advisable.

Hello
I do not think you want to set up instance variables in this case.
I think you want to just modify how the .get() method works for the new dictionary class…

I have some code I used to satisfy this, as well as some print tests comparing the behavior to that of a built in dictionary.

class NewDic(dict):
  def get(self, key):
    super().get(key)
    if key not in self.keys():
      return "this is not the answer"
    else:
      return self[key]

nudick = NewDic({42: 'this is the answer', })
print(nudick.get(41))
print(nudick.get(42))

olddikk ={"key":"value"}
print(olddikk.get("skey"))
print(olddikk.get('key'))

5 posts were split to a new topic: Is there a way to somehow see what parameters are in the list.init(…questioned parameters…) constructor?

I’ve also had that problem, but with the help of omaiskhan4987806592 and later link from wanjapm i think we can code something like this:

class NewDict(dict):
  fallback_value = "The key is missing"

  def __missing__(self, key):
    return self.fallback_value

# # To test code uncomment bellow
# dict_a = NewDict()
# print(dict_a)
#
# dict_a.update({"kaka": "didi", "pipi": "jojo"})
# print(dict_a["kaka"], dict_a["pipi"])
#
# print(dict_a["kakas"])

…and call it a day :slight_smile:

image
In this code, ı had figured out using of init but couldn’t manage to find which parametres to place. The code in the image is not belong to me i just wanted to show the part which i didn’t understand. Here in this image, why we placed random (“dc”) argument and how does it work ? Shouldn’t we supossed to place the arguments which are belong to parent class (dict) when we are using super() func ? I tried to change “dc” parametre and it stills work how can it be ?

Hi, could you please explain what the init method in NewDict class does? I tried both including it and removing it, but the result remained the same.
And were you able to print the fallback message? I only received KeyError.

Could someone explain why the first printed list is sorted, please? The self.sort() method is within the append function and how does list = SortedList([9, 2, 7]) get sorted without calling list.append()?

Thank you very much

Follow the order of what happens when you first create an instance of that class and you might notice that append comes in somewhere.

1 Like

There’s no need to override the __init__ of the default dict class at all, as noted by @eluscha. I guess people just thought they would have to override it in the same way as in the SortedList challenge, but we don’t need to do that here.

This is my solution:

class SortedList(list):
  def __init__(self, init_list):
    super().__init__(init_list)
    super().sort()
  def append(self, value):
    super().append(value)
    super().sort()
sorted_list = SortedList([9, 0, 4, 1, 5])
sorted_list.append(8)
print(sorted_list)

class FallbackDict(dict):
  def get(self, key):
    if key not in super().keys():
      return "Nothing to say"
    else:
      return super().get(key)
fallback_dict = FallbackDict({1 : "Hi", 2 : "Bye"})
print(fallback_dict.get(1))
print(fallback_dict.get(2))
print(fallback_dict.get(3))

For the dictionary challenge, this is my solution. It works, but not sure if anything is missing here and if I solved it correctly:

class NewDic(dict):
  def __missing__(self,key):
    return "Item not available"
test_dict = NewDic({'A':1,'B':2})
print(test_dict['C'])
#print Item not available

I came up with this after refering to this Built-in Types — Python 3.9.6 documentation which pretty much shows me how to solve the challenge.

Like several people in this thread I was stuck on the first bonus question about sorting the initial list.

class SortedList(list):
    def __init__(self, lst):
        super().__init__(lst)
        self.sort()

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

This answer makes sense, but without giving explicit knowledge of how __init__() works for the class list how would someone reasonably come to this conclusion. Were we supposed to go look for source or documentation, was this mentioned somewhere and I missed it, or is there another solution?

You can run help(list) but even this doesn’t give a lot of clues. I just want to make sure I’m thinking in a way that is conducive to solving this problem with the knowledge given up to this point.