Home > Enterprise >  trying to make subclass but nothing seems to work :(
trying to make subclass but nothing seems to work :(

Time:11-23

So i'm basicly trying to fetch some data from the duolingo api and make all the different parts accesible via a class (I think that's the best way to make the data accesible in other files?)

I currently have this code:

class DuoData:
    def __init__(self, username):
        self.username = username
        self.URL = "https://www.duolingo.com/2017-06-30/users?username={username}"
        self.data = requests.get(self.URL.format(username=self.username))
        self.data_json = self.data.json()

    def get_streak(self):
        return self.data_json['users'][0]['streak']

    class ActiveLanguage:
        def __init__(self, data_json):
            super().__init__()
            self.active_language = data_json['users'][0]['courses'][0]
        
        def get_name(self):
            return self.active_language['title']

        def get_xp(self):
            return self.active_language['xp']
        
        def get_crowns(self):
            return self.active_language['crowns']

the get_streak fucntion works perfectly, so

duo = DuoData("username")
print(duo.get_streak())

prints the streak number like I want, but the following code doesn't work: print(duo.ActiveLanguage.get_name())

I want it so that duo.ActiveLanguage.getname() returns the name of the language but it doesn't work like this, I get the following error: TypeError: DuoData.ActiveLanguage.get_name() missing 1 required positional argument: 'self' I already tried lots of different things and this was my best approach but it still doesn't work, can anyone help me? This is my first time working with classes (in Python) I think maybe subclasses aren't the right approach?

My question is: can i have a class or whatever with a few categories that each have different values? like: data.userdata.streak and data.userdata.id and data.activelanguage.name and so on?

CodePudding user response:

This is how you would do a subclass. A subclass means that ActiveLanguage is a specific kind of DuoData.

However, in this particular case, I'm not sure that's what you want. It may be you want "encapsulation", where ActiveLanguage is a class that stands alone and USES an instance of DuoData to do its work.

class DuoData:
    def __init__(self, username):
        self.username = username
        self.URL = "https://www.duolingo.com/2017-06-30/users?username={username}"
        self.data = requests.get(self.URL.format(username=self.username))
        self.data_json = self.data.json()

    def get_streak(self):
        return self.data_json['users'][0]['streak']

class ActiveLanguage(DuoData)
    def __init__(self, username):
        super().__init__(username)
        self.active_language = self.data_json['users'][0]['courses'][0]
    
    def get_name(self):
        return self.active_language['title']

    def get_xp(self):
        return self.active_language['xp']
    
    def get_crowns(self):
        return self.active_language['crowns']

duo = DuoData("username")
print(duo.get_streak())
acl = ActiveLanguage("username")
print(acl.get_streak())
print(acl.get_name())

CodePudding user response:

First of all, thanks to Tim and Rhurwitz, I threw your code together and it magically worked! This is the code:

import requests

class DuoData:
    def __init__(self, username):
        self.username = username
        self.URL = "https://www.duolingo.com/2017-06-30/users?username={username}"
        self.data = requests.get(self.URL.format(username=self.username))
        self.data_json = self.data.json()
        self.active = self.ActiveLanguage(self.data_json['users'][0]['courses'][0])

    def get_streak(self):
        return self.data_json['users'][0]['streak']

    class ActiveLanguage:
        def __init__(self, active_language):
            self.active_language = active_language
        
        def get_name(self):
            return self.active_language['title']

        def get_xp(self):
            return self.active_language['xp']
        
        def get_crowns(self):
            return self.active_language['crowns']


duo = DuoData("Infinibyte")
print(duo.get_streak())
print(duo.active.get_name())
print(duo.active.get_xp())
print(duo.active.get_crowns())

It works just like I want. However, I do not understand what I did (subclasses, nested classes, ... idk) so any explanation would be welcome ;)

CodePudding user response:

Are you sure you want a subclass? If ActiveLanguage is a subclass of DuoData then you are, in effect, saying that ActiveLanguage "is-a" DuoData which does not seem to be your intent. If your intent is to say that DuoData "has-a" ActiveLanguage attribute then you may want to use composition rather than inheritance:

class ActiveLanguage:
    def __init__(self, active_language):
        self.active_language = active_language
    
    def get_name(self):
        return self.active_language['title']

    def get_xp(self):
        return self.active_language['xp']
    
    def get_crowns(self):
        return self.active_language['crowns']

class DuoData:
    def __init__(self, username):
        self.username = username
        self.URL = "https://www.duolingo.com/2017-06-30/users?username={username}"
        self.data = requests.get(self.URL.format(username=self.username))
        self.data_json = self.data.json()

    def get_streak(self):
        return self.data_json['users'][0]['streak']

    def get_active_language(self):
        return ActiveLanguage(self.data_json['users'][0]['courses'][0])


duo = DuoData("username")
print(duo.get_streak())
acl = duo.get_active_language()
print(acl.get_name())

Edit: Fixed a cut and paste error by changing:

return self.ActiveLanguage(self.data_json['users'][0]['courses'][0])

to:

return ActiveLanguage(self.data_json['users'][0]['courses'][0])

Thanks to @Tim and @Infinibyte for spotting it.

  • Related