Sylent Nyte Sylent Nyte - 5 months ago 44
Python Question

Python - Nested Classes (Parent-Child [New to Classes])

I have this data

{Wednesday : {22 : {Type = x,
Temp = x,
Speed = x,
Direction = x}
{23 : {Type = x,
Temp = x,
Speed = x,
Direction = x}


I am trying to write a class so that I will be able to access it by calling as an example and that will give me X.

My code so far is this :

class Weather(object):
def __init__(self, wtype, wtemp, wspeed, wdirection):
self.type = wtype
self.temp = wtemp
self.speed = wspeed
self.direction = wdirection


This allows me to get the data when calling upon the date :

Wednesday.Temp
>>> 22


However I also need to allocate the data by time as well as the date, so when calling
"Wednesday.22.Type"
I get the specific date for that our.

I am new to classes within Python and I'm not quite sure on how to build the class so that I can call on the date, and then the time to get the respective data. I'm assuming that a nested class is needed to have a "parent-child" like relation in the code however I'm not sure how to do this.

Answer

Although numbers are not considered to be valid identifiers in Python (but that could be funny for trolling: 0 = 1 = 2 = 3 = 42), things like _3 are, but are generally considered to be "private" attributes by the python community (myself included), so i use at followed by the number instead. And I think it would be better to access it like you access a dictionary.

Here is my take on it. Remove the methods if you don't want the associated feature.

class SpecificWeather(object):
    def __init__(self, data):
        self.data = data

    @property
    def type(self):
        return self.data["Type"]

    @property
    def temperature(self):
        return self.data["Temp"]

    @property
    def speed(self):
        return self.data["Speed"]

    @property
    def direction(self):
        return self.data["Direction"]


class Weather(object):
    def __init__(self, data):  # data is the dictionary
        self.data = data

    def __getitem___(self, item):  # for wednesday[22].type
        return SpecificWeather(self.data[item])

    def __getattr__(self, name):  # for wednesday.at22.type
        if name.startswith("at"):
            return SpecificWeather(self.data[int(name[2:])])
        raise AttributeError()

    @property
    def type(self):
        # TODO: Return the average type or something like that

    @property
    def temperature(self):
        # TODO: Return the average temperature or something like that

    @property
    def speed(self):
        # TODO: Return the average speed or something like that

    @property
    def direction(self):
        # TODO: Return the average direction or something like that

This solution uses property a lot, this has a big advantage: If you change the temperate for 22, wednesday[22].temperature will now give you the new value. If you care for performance however, and you use only half of them, then this one can be faster than storing the results, if you access them even multiple times though, this will be a lot slower.

How to use it:

wednesday = Weather({
    22: {
        'Type': ...,
        'Temp': 30,
        'Speed': ...,
        'Direction': ...
    },
    23: {
        'Type': ...,
        'Temp': 28,
        'Speed': ...,
        'Direction': ...
    }
})

print(wednesday.at22.temperature)  # gives 30
print(wednesday[23].temperature)  # gives 28