J L
J L

Reputation: 987

Inheritance in Python, init method overrriding

I'm trying to understand inheritance in Python. I have 4 different kind of logs that I want to process: cpu, ram, net and disk usage

I decided to implement this with classes, as they're formally the same except for the log file reading and the data type for the data. I have a the following code (log object is a logging object instance of a custom logging class)

class LogFile():    
    def __init__(self,log_file):
        self._log_file=log_file
        self.validate_log()

    def validate_log(self):
        try:
            with open(self._log_file) as dummy_log_file:
                pass
        except IOError as e:
               log.log_error(str(e[0])+' '+e[1]+' for log file '+self._log_file)

class Data(LogFile):
    def __init__(self,log_file):
        LogFile.__init__(self, log_file)
        self._data=''

    def get_data(self):
        return self._data

    def set_data(self,data):
        self._data=data

    def validate_data(self):
        if self._data == '':
            log.log_debug("Empty data list")

class DataCPU(Data):    
    def read_log(self):            
        self.validate_log()
        reading and writing to LIST stuff

        return LIST


class DataRAM(Data):
    def read_log(self):            
        self.validate_log()    
        reading and writing to LIST stuff

        return LIST

class DataNET(Data):

Now I want my DataNET class to be a object of the Data Class with some more attributes, in particular a dictionary for every one of the interfaces. How can I override the __init__() method to be the same as the Data.__init__() but adding self.dict={} without copying the Data builder? This is, without explicitly specifing the DataNet objects do have a ._data attribute, but inherited from Data.

Upvotes: 1

Views: 159

Answers (2)

ElmoVanKielmo
ElmoVanKielmo

Reputation: 11315

Use new style classes (inherit from object) - change definition of LogFile to:

class LogFile(object):

and init method of Data to:

def __init__(self, log_file):
    super(Data, self).__init__(log_file)
    self._data = ''

Then you can define DataNET as:

class DataNET(Data):
    def __init__(self, log_file):
        super(DataNET, self).__init__(log_file)
        self.dict = {}

Upvotes: 2

Martijn Pieters
Martijn Pieters

Reputation: 1124208

Just call the Data.__init__() method from DataNET.__init__(), then set self._data = {}:

class DataNET(Data):
    def __init__(self, logfile):
        Data.__init__(self, logfile)
        self._data = {}

Now whatever Data.__init__() does to self happens first, leaving your DataNET initializer to add new attributes or override attributes set by the parent initializer.

In Python 3 classes are already new-style, but if this is Python 2, I'd add object as a base class to LogFile() to make it new-style too:

class LogFile(object):

after which you can use super() to automatically look up the parent __init__ method to call; this has the advantage that in a more complex cooperative inheritance scheme the right methods are invoked in the right order:

class Data(LogFile):
    def __init__(self,log_file):
        super(Data, self).__init__(log_file)
        self._data = ''

class DataNET(Data):
    def __init__(self, logfile):
        super(DataNET, self).__init__(logfile)
        self._data = {}

super() provides you with bound methods, so you don't need to pass in self as an argument to __init__ in that case. In Python 3, you can omit the arguments to super() altogether:

class Data(LogFile):
    def __init__(self,log_file):
        super().__init__(log_file)
        self._data = ''

class DataNET(Data):
    def __init__(self, logfile):
        super().__init__(logfile)
        self._data = {}

Upvotes: 3

Related Questions