TransWikia.com

I am a little bit confused by the super().__init__()

Stack Overflow Asked by Nick Yang on December 13, 2021

Here is my code:

class StrKeyDict(dict):
    def __init__(self):
        super().__init__()

    def __missing__(self, key):
        if isinstance(key, str):
            raise KeyError(key)
        return self[str(key)]

    def __contains__(self, key):
        return key in self.keys() or str(key) in self.keys()

    def get(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            return default

if __name__ == "__main__":
    d = StrKeyDict([('2', 'two'), ('4', "four")])

I want to inherit the build-in dict, so I use super(). But when I use StrKeyDict([('2', 'two'), ('4', "four")]) to initialize it, error comes like this:

Traceback (most recent call last):
  File "/Users/nick/PyProjects/Fluent-Python/3-6.py", line 25, in <module>
    d = StrKeyDict([('2', 'two'), ('4', "four")])
TypeError: __init__() takes 1 positional argument but 2 were given

However, if I delete __init__() the whole class will work just fine. So my question is:

  1. Is super().__init__() a must in every class?
  2. If I want to keep super().__init__(), how would I modify?

4 Answers

Is super().__init__() a must in every class?

No, you only need it when you want to run the inherited __init__ and do something extra, like only allowing certain parameters, or further mutating self afterwards.

In this case, where StrKeyDict.__init__() doesn't do anything extra, you should remove it and let StrKeyDict inherit dict.__init__().

If I want to keep super().__init__(), how would I modify?

You would need StrKeyDict.__init__() to take arguments and pass them to super().__init__().

If you want to be permissive/lazy, you can allow anything:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)

Or if you want to be restrictive, match the signature of dict.__init__():

def __init__(self, mapping_or_iterable, **kwargs):
    super().__init__(mapping_or_iterable, **kwargs)

P.S. I've let out some nuances here, but this should be enough to get you on your way.

Answered by wjandrea on December 13, 2021

  • Whenever you create a new instance of a class init method is called. It's like a constructer. Since your init method need not require any argument but you are passing a list, that's why you are getting this error. When you call the super method init method of inherited class is being called.

Here is rectified code:

class StrKeyDict(dict):
    def __init__(self,lst):
        super().__init__(lst)

    def __missing__(self, key):
        if isinstance(key, str):
            raise KeyError(key)
        return self[str(key)]

    def __contains__(self, key):
        return key in self.keys() or str(key) in self.keys()

    def get(self, key, default=None):
        try:
            return self[key]
        except KeyError:
            return default

if __name__ == "__main__":
    d = StrKeyDict([('2', 'two'), ('4', "four")])

Answered by TheSohan on December 13, 2021

The error is raised because your call to create a StrKeyDict passed in the array and you did not allow for it in __init__'s parameters. it should have been:

def __init__(self,  my_list):
   ...

etc

Answered by LhasaDad on December 13, 2021

By doing this class StrKeyDict(dict): you inherit dict, there is no need for init unless you want to initialize something when the class is created.

Answered by Crapy on December 13, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP